about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-07-02 12:47:32 -0700
committerPatrick Walton <pcwalton@mimiga.net>2013-07-17 14:57:51 -0700
commit99b33f721954bc5290f9201c8f64003c294d0571 (patch)
tree786c9bf75d54512d0a80f6975ad40516ab432c3a
parentb4e674f6e662bc80f2e7a5a1a9834f2152f08d32 (diff)
downloadrust-99b33f721954bc5290f9201c8f64003c294d0571.tar.gz
rust-99b33f721954bc5290f9201c8f64003c294d0571.zip
librustc: Remove all uses of "copy".
-rw-r--r--src/compiletest/compiletest.rs16
-rw-r--r--src/compiletest/procsrv.rs2
-rw-r--r--src/compiletest/runtest.rs18
-rw-r--r--src/libextra/arc.rs2
-rw-r--r--src/libextra/base64.rs14
-rw-r--r--src/libextra/bitv.rs4
-rw-r--r--src/libextra/c_vec.rs8
-rw-r--r--src/libextra/dlist.rs4
-rw-r--r--src/libextra/ebml.rs11
-rw-r--r--src/libextra/fileinput.rs21
-rw-r--r--src/libextra/flatpipes.rs38
-rw-r--r--src/libextra/fun_treemap.rs6
-rw-r--r--src/libextra/future.rs4
-rw-r--r--src/libextra/getopts.rs73
-rw-r--r--src/libextra/json.rs58
-rw-r--r--src/libextra/list.rs26
-rw-r--r--src/libextra/net/ip.rs13
-rw-r--r--src/libextra/net/tcp.rs20
-rw-r--r--src/libextra/num/bigint.rs26
-rw-r--r--src/libextra/par.rs15
-rw-r--r--src/libextra/priority_queue.rs4
-rw-r--r--src/libextra/ringbuf.rs58
-rw-r--r--src/libextra/semver.rs4
-rw-r--r--src/libextra/smallintmap.rs4
-rw-r--r--src/libextra/sort.rs62
-rw-r--r--src/libextra/stats.rs2
-rw-r--r--src/libextra/terminfo/parm.rs13
-rw-r--r--src/libextra/test.rs49
-rw-r--r--src/libextra/time.rs4
-rw-r--r--src/libextra/treemap.rs4
-rw-r--r--src/libextra/uv_ll.rs12
-rw-r--r--src/libextra/workcache.rs17
-rw-r--r--src/librust/rust.rs4
-rw-r--r--src/librustc/back/link.rs10
-rw-r--r--src/librustc/back/rpath.rs2
-rw-r--r--src/librustc/driver/driver.rs52
-rw-r--r--src/librustc/driver/session.rs16
-rw-r--r--src/librustc/front/config.rs18
-rw-r--r--src/librustc/front/std_inject.rs6
-rw-r--r--src/librustc/front/test.rs39
-rw-r--r--src/librustc/lib/llvm.rs1
-rw-r--r--src/librustc/metadata/creader.rs17
-rw-r--r--src/librustc/metadata/cstore.rs13
-rw-r--r--src/librustc/metadata/decoder.rs5
-rw-r--r--src/librustc/metadata/encoder.rs39
-rw-r--r--src/librustc/metadata/filesearch.rs7
-rw-r--r--src/librustc/metadata/loader.rs8
-rw-r--r--src/librustc/metadata/tyencode.rs10
-rw-r--r--src/librustc/middle/astencode.rs12
-rw-r--r--src/librustc/middle/borrowck/mod.rs9
-rw-r--r--src/librustc/middle/borrowck/move_data.rs24
-rw-r--r--src/librustc/middle/check_const.rs17
-rw-r--r--src/librustc/middle/check_loop.rs1
-rw-r--r--src/librustc/middle/check_match.rs2
-rw-r--r--src/librustc/middle/const_eval.rs50
-rw-r--r--src/librustc/middle/dataflow.rs31
-rw-r--r--src/librustc/middle/freevars.rs2
-rw-r--r--src/librustc/middle/kind.rs1
-rw-r--r--src/librustc/middle/lint.rs15
-rw-r--r--src/librustc/middle/liveness.rs7
-rw-r--r--src/librustc/middle/moves.rs2
-rw-r--r--src/librustc/middle/privacy.rs2
-rw-r--r--src/librustc/middle/reachable.rs2
-rw-r--r--src/librustc/middle/region.rs1
-rw-r--r--src/librustc/middle/resolve.rs31
-rw-r--r--src/librustc/middle/trans/_match.rs19
-rw-r--r--src/librustc/middle/trans/adt.rs6
-rw-r--r--src/librustc/middle/trans/base.rs58
-rw-r--r--src/librustc/middle/trans/build.rs2
-rw-r--r--src/librustc/middle/trans/cabi.rs1
-rw-r--r--src/librustc/middle/trans/cabi_x86_64.rs2
-rw-r--r--src/librustc/middle/trans/callee.rs2
-rw-r--r--src/librustc/middle/trans/closure.rs4
-rw-r--r--src/librustc/middle/trans/common.rs43
-rw-r--r--src/librustc/middle/trans/debuginfo.rs4
-rw-r--r--src/librustc/middle/trans/expr.rs3
-rw-r--r--src/librustc/middle/trans/foreign.rs18
-rw-r--r--src/librustc/middle/trans/glue.rs4
-rw-r--r--src/librustc/middle/trans/inline.rs3
-rw-r--r--src/librustc/middle/trans/meth.rs45
-rw-r--r--src/librustc/middle/trans/monomorphize.rs27
-rw-r--r--src/librustc/middle/trans/reflect.rs2
-rw-r--r--src/librustc/middle/trans/type_.rs2
-rw-r--r--src/librustc/middle/trans/type_use.rs32
-rw-r--r--src/librustc/middle/ty.rs167
-rw-r--r--src/librustc/middle/typeck/astconv.rs49
-rw-r--r--src/librustc/middle/typeck/check/_match.rs29
-rw-r--r--src/librustc/middle/typeck/check/method.rs30
-rw-r--r--src/librustc/middle/typeck/check/mod.rs85
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs26
-rw-r--r--src/librustc/middle/typeck/coherence.rs13
-rw-r--r--src/librustc/middle/typeck/collect.rs59
-rw-r--r--src/librustc/middle/typeck/infer/coercion.rs20
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs18
-rw-r--r--src/librustc/middle/typeck/infer/lattice.rs114
-rw-r--r--src/librustc/middle/typeck/infer/mod.rs40
-rw-r--r--src/librustc/middle/typeck/infer/unify.rs81
-rw-r--r--src/librustc/middle/typeck/mod.rs8
-rw-r--r--src/librustc/middle/typeck/rscope.rs21
-rw-r--r--src/librustc/rustc.rs12
-rw-r--r--src/librustc/util/enum_set.rs2
-rw-r--r--src/librustc/util/ppaux.rs2
-rw-r--r--src/librustdoc/astsrv.rs7
-rw-r--r--src/librustdoc/attr_pass.rs40
-rw-r--r--src/librustdoc/config.rs25
-rw-r--r--src/librustdoc/desc_to_brief_pass.rs18
-rw-r--r--src/librustdoc/doc.rs98
-rw-r--r--src/librustdoc/extract.rs10
-rw-r--r--src/librustdoc/fold.rs50
-rw-r--r--src/librustdoc/markdown_index_pass.rs18
-rw-r--r--src/librustdoc/markdown_pass.rs60
-rw-r--r--src/librustdoc/markdown_writer.rs11
-rw-r--r--src/librustdoc/page_pass.rs49
-rw-r--r--src/librustdoc/parse.rs2
-rw-r--r--src/librustdoc/pass.rs8
-rw-r--r--src/librustdoc/path_pass.rs8
-rw-r--r--src/librustdoc/prune_hidden_pass.rs6
-rw-r--r--src/librustdoc/prune_private_pass.rs10
-rw-r--r--src/librustdoc/rustdoc.rs9
-rw-r--r--src/librustdoc/sectionalize_pass.rs20
-rw-r--r--src/librustdoc/sort_pass.rs18
-rw-r--r--src/librustdoc/text_pass.rs72
-rw-r--r--src/librustdoc/trim_pass.rs2
-rw-r--r--src/librustdoc/tystr_pass.rs34
-rw-r--r--src/librustdoc/util.rs19
-rw-r--r--src/librusti/program.rs12
-rw-r--r--src/librusti/rusti.rs24
-rw-r--r--src/librustpkg/api.rs6
-rw-r--r--src/librustpkg/crate.rs19
-rw-r--r--src/librustpkg/package_id.rs5
-rw-r--r--src/librustpkg/package_path.rs20
-rw-r--r--src/librustpkg/package_source.rs18
-rw-r--r--src/librustpkg/path_util.rs21
-rw-r--r--src/librustpkg/rustpkg.rs18
-rw-r--r--src/librustpkg/tests.rs16
-rw-r--r--src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs4
-rw-r--r--src/librustpkg/util.rs34
-rw-r--r--src/librustpkg/version.rs1
-rw-r--r--src/libstd/at_vec.rs35
-rw-r--r--src/libstd/cast.rs8
-rw-r--r--src/libstd/condition.rs2
-rw-r--r--src/libstd/either.rs10
-rw-r--r--src/libstd/hashmap.rs21
-rw-r--r--src/libstd/io.rs23
-rw-r--r--src/libstd/local_data.rs8
-rw-r--r--src/libstd/num/strconv.rs19
-rw-r--r--src/libstd/option.rs12
-rw-r--r--src/libstd/os.rs21
-rw-r--r--src/libstd/path.rs78
-rw-r--r--src/libstd/ptr.rs11
-rw-r--r--src/libstd/rand.rs33
-rw-r--r--src/libstd/result.rs60
-rw-r--r--src/libstd/rt/join_latch.rs18
-rw-r--r--src/libstd/run.rs3
-rw-r--r--src/libstd/str.rs9
-rw-r--r--src/libstd/tuple.rs24
-rw-r--r--src/libstd/util.rs6
-rw-r--r--src/libstd/vec.rs78
-rw-r--r--src/libsyntax/abi.rs2
-rw-r--r--src/libsyntax/ast.rs174
-rw-r--r--src/libsyntax/ast_map.rs38
-rw-r--r--src/libsyntax/ast_util.rs96
-rw-r--r--src/libsyntax/attr.rs8
-rw-r--r--src/libsyntax/codemap.rs11
-rw-r--r--src/libsyntax/diagnostic.rs8
-rw-r--r--src/libsyntax/ext/base.rs4
-rw-r--r--src/libsyntax/ext/build.rs6
-rw-r--r--src/libsyntax/ext/deriving/generic.rs25
-rw-r--r--src/libsyntax/ext/deriving/iter_bytes.rs5
-rw-r--r--src/libsyntax/ext/deriving/rand.rs8
-rw-r--r--src/libsyntax/ext/deriving/zero.rs2
-rw-r--r--src/libsyntax/ext/expand.rs10
-rw-r--r--src/libsyntax/ext/pipes/ast_builder.rs8
-rw-r--r--src/libsyntax/ext/pipes/mod.rs2
-rw-r--r--src/libsyntax/ext/pipes/parse_proto.rs2
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs18
-rw-r--r--src/libsyntax/ext/pipes/proto.rs6
-rw-r--r--src/libsyntax/ext/quote.rs2
-rw-r--r--src/libsyntax/ext/source_util.rs2
-rw-r--r--src/libsyntax/ext/trace_macros.rs6
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs24
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs13
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs42
-rw-r--r--src/libsyntax/fold.rs39
-rw-r--r--src/libsyntax/opt_vec.rs4
-rw-r--r--src/libsyntax/parse/attr.rs14
-rw-r--r--src/libsyntax/parse/comments.rs4
-rw-r--r--src/libsyntax/parse/lexer.rs16
-rw-r--r--src/libsyntax/parse/mod.rs14
-rw-r--r--src/libsyntax/parse/obsolete.rs8
-rw-r--r--src/libsyntax/parse/parser.rs846
-rw-r--r--src/libsyntax/parse/token.rs10
-rw-r--r--src/libsyntax/print/pp.rs20
-rw-r--r--src/libsyntax/print/pprust.rs42
-rw-r--r--src/libsyntax/util/interner.rs12
-rw-r--r--src/libsyntax/visit.rs277
-rw-r--r--src/test/auxiliary/cci_capture_clause.rs4
-rw-r--r--src/test/auxiliary/cci_class_cast.rs2
-rw-r--r--src/test/auxiliary/cci_nested_lib.rs12
-rw-r--r--src/test/auxiliary/issue-2631-a.rs4
-rw-r--r--src/test/auxiliary/issue2378a.rs4
-rw-r--r--src/test/auxiliary/issue2378b.rs2
-rw-r--r--src/test/auxiliary/issue4516_ty_param_lib.rs4
-rw-r--r--src/test/auxiliary/issue_2242_a.rs2
-rw-r--r--src/test/bench/graph500-bfs.rs22
-rw-r--r--src/test/bench/msgsend-pipes-shared.rs4
-rw-r--r--src/test/bench/msgsend-pipes.rs6
-rw-r--r--src/test/bench/msgsend-ring-mutex-arcs.rs2
-rw-r--r--src/test/bench/msgsend-ring-pipes.rs2
-rw-r--r--src/test/bench/msgsend-ring-rw-arcs.rs2
-rw-r--r--src/test/bench/shootout-fasta.rs13
-rw-r--r--src/test/bench/shootout-k-nucleotide-pipes.rs29
-rw-r--r--src/test/bench/shootout-pfib.rs2
-rw-r--r--src/test/bench/task-perf-jargon-metal-smoke.rs2
-rw-r--r--src/test/bench/task-perf-linked-failure.rs2
-rw-r--r--src/test/compile-fail/borrowck-lend-flow-match.rs2
-rw-r--r--src/test/compile-fail/borrowck-move-out-of-vec-tail.rs3
-rw-r--r--src/test/compile-fail/borrowck-pat-reassign-binding.rs2
-rw-r--r--src/test/compile-fail/by-move-pattern-binding.rs2
-rw-r--r--src/test/compile-fail/copy-a-resource.rs4
-rw-r--r--src/test/compile-fail/infinite-instantiation.rs6
-rw-r--r--src/test/compile-fail/issue-2823.rs2
-rw-r--r--src/test/compile-fail/issue-4542.rs2
-rw-r--r--src/test/compile-fail/kindck-owned.rs11
-rw-r--r--src/test/compile-fail/liveness-assign-imm-local-in-loop.rs2
-rw-r--r--src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs2
-rw-r--r--src/test/compile-fail/liveness-assign-imm-local-with-init.rs4
-rw-r--r--src/test/compile-fail/liveness-dead.rs8
-rw-r--r--src/test/compile-fail/liveness-init-in-fru.rs9
-rw-r--r--src/test/compile-fail/liveness-init-op-equal.rs2
-rw-r--r--src/test/compile-fail/liveness-init-plus-equal.rs2
-rw-r--r--src/test/compile-fail/liveness-move-in-loop.rs2
-rw-r--r--src/test/compile-fail/liveness-move-in-while.rs2
-rw-r--r--src/test/compile-fail/liveness-use-after-move.rs2
-rw-r--r--src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs8
-rw-r--r--src/test/compile-fail/non-copyable-void.rs4
-rw-r--r--src/test/compile-fail/noncopyable-class.rs2
-rw-r--r--src/test/compile-fail/pinned-deep-copy.rs7
-rw-r--r--src/test/compile-fail/unique-object-noncopyable.rs2
-rw-r--r--src/test/compile-fail/unique-pinned-nocopy.rs4
-rw-r--r--src/test/compile-fail/unique-vec-res.rs5
-rw-r--r--src/test/run-fail/unwind-box-fn-unique.rs2
-rw-r--r--src/test/run-fail/unwind-box-fn.rs2
-rw-r--r--src/test/run-fail/unwind-lambda.rs4
-rw-r--r--src/test/run-fail/unwind-misc-1.rs2
-rw-r--r--src/test/run-pass/alignment-gep-tup-like-1.rs4
-rw-r--r--src/test/run-pass/alignment-gep-tup-like-2.rs6
-rw-r--r--src/test/run-pass/borrowed-ptr-pattern.rs4
-rw-r--r--src/test/run-pass/box-unbox.rs2
-rw-r--r--src/test/run-pass/class-cast-to-trait-multiple-types.rs3
-rw-r--r--src/test/run-pass/class-implement-traits.rs3
-rw-r--r--src/test/run-pass/close-over-big-then-small-data.rs4
-rw-r--r--src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs23
-rw-r--r--src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs26
-rw-r--r--src/test/run-pass/explicit-self.rs9
-rw-r--r--src/test/run-pass/expr-block-generic-box2.rs4
-rw-r--r--src/test/run-pass/expr-block-generic-unique2.rs4
-rw-r--r--src/test/run-pass/expr-block-generic.rs10
-rw-r--r--src/test/run-pass/expr-if-generic-box2.rs4
-rw-r--r--src/test/run-pass/expr-if-generic.rs10
-rw-r--r--src/test/run-pass/expr-match-generic-box2.rs4
-rw-r--r--src/test/run-pass/expr-match-generic.rs10
-rw-r--r--src/test/run-pass/generic-derived-type.rs12
-rw-r--r--src/test/run-pass/getopts_ref.rs2
-rw-r--r--src/test/run-pass/issue-2804.rs27
-rw-r--r--src/test/run-pass/issue-4241.rs2
-rw-r--r--src/test/run-pass/ivec-add.rs2
-rw-r--r--src/test/run-pass/kindck-owned-trait-contains-1.rs8
-rw-r--r--src/test/run-pass/move-1-unique.rs13
-rw-r--r--src/test/run-pass/move-3-unique.rs9
-rw-r--r--src/test/run-pass/newtype-polymorphic.rs9
-rw-r--r--src/test/run-pass/nullable-pointer-iotareduction.rs15
-rw-r--r--src/test/run-pass/overload-index-operator.rs9
-rw-r--r--src/test/run-pass/reflect-visit-data.rs4
-rw-r--r--src/test/run-pass/resource-generic.rs40
-rw-r--r--src/test/run-pass/sendfn-generic-fn.rs14
-rw-r--r--src/test/run-pass/shape_intrinsic_tag_then_rec.rs37
-rw-r--r--src/test/run-pass/unique-copy-box.rs2
278 files changed, 3186 insertions, 2600 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index 39dc55b44f4..76e3f2f32ee 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -117,9 +117,11 @@ pub fn parse_config(args: ~[~str]) -> config {
         mode: str_mode(getopts::opt_str(matches, "mode")),
         run_ignored: getopts::opt_present(matches, "ignored"),
         filter:
-             if !matches.free.is_empty() {
-                 Some(copy matches.free[0])
-             } else { None },
+            if !matches.free.is_empty() {
+                 Some(matches.free[0].clone())
+            } else {
+                None
+            },
         logfile: getopts::opt_maybe_str(matches, "logfile").map(|s| Path(*s)),
         save_metrics: getopts::opt_maybe_str(matches, "save-metrics").map(|s| Path(*s)),
         ratchet_metrics:
@@ -223,9 +225,9 @@ pub fn run_tests(config: &config) {
 
 pub fn test_opts(config: &config) -> test::TestOpts {
     test::TestOpts {
-        filter: copy config.filter,
+        filter: config.filter.clone(),
         run_ignored: config.run_ignored,
-        logfile: copy config.logfile,
+        logfile: config.logfile.clone(),
         run_tests: true,
         run_benchmarks: true,
         ratchet_metrics: copy config.ratchet_metrics,
@@ -240,7 +242,7 @@ pub fn make_tests(config: &config) -> ~[test::TestDescAndFn] {
     let mut tests = ~[];
     let dirs = os::list_dir_path(&config.src_base);
     for dirs.iter().advance |file| {
-        let file = copy *file;
+        let file = (*file).clone();
         debug!("inspecting file %s", file.to_str());
         if is_test(config, file) {
             let t = do make_test(config, file) {
@@ -306,7 +308,7 @@ pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName {
 
 pub fn make_test_closure(config: &config, testfile: &Path) -> test::TestFn {
     use std::cell::Cell;
-    let config = Cell::new(copy *config);
+    let config = Cell::new((*config).clone());
     let testfile = Cell::new(testfile.to_str());
     test::DynTestFn(|| { runtest::run(config.take(), testfile.take()) })
 }
diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs
index 0e61b45d619..ac87eabc0fd 100644
--- a/src/compiletest/procsrv.rs
+++ b/src/compiletest/procsrv.rs
@@ -22,7 +22,7 @@ fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] {
     let aux_path = prog.slice(0u, prog.len() - 4u).to_owned() + ".libaux";
 
     env = do env.map() |pair| {
-        let (k,v) = copy *pair;
+        let (k,v) = (*pair).clone();
         if k == ~"PATH" { (~"PATH", v + ";" + lib_path + ";" + aux_path) }
         else { (k,v) }
     };
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index a51ab820856..f071c204810 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -150,7 +150,7 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) {
     let mut round = 0;
     while round < rounds {
         logv(config, fmt!("pretty-printing round %d", round));
-        let ProcRes = print_source(config, testfile, copy srcs[round]);
+        let ProcRes = print_source(config, testfile, srcs[round].clone());
 
         if ProcRes.status != 0 {
             fatal_ProcRes(fmt!("pretty-printing failed in round %d", round),
@@ -168,9 +168,9 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) {
             let filepath = testfile.dir_path().push_rel(file);
             io::read_whole_file_str(&filepath).get()
           }
-          None => { copy srcs[srcs.len() - 2u] }
+          None => { srcs[srcs.len() - 2u].clone() }
         };
-    let mut actual = copy srcs[srcs.len() - 1u];
+    let mut actual = srcs[srcs.len() - 1u].clone();
 
     if props.pp_exact.is_some() {
         // Now we have to care about line endings
@@ -243,13 +243,13 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
     let mut config = match config.rustcflags {
         Some(ref flags) => config {
             rustcflags: Some(flags.replace("-O", "")),
-            .. copy *config
+            .. (*config).clone()
         },
-        None => copy *config
+        None => (*config).clone()
     };
     let config = &mut config;
     let cmds = props.debugger_cmds.connect("\n");
-    let check_lines = copy props.check_lines;
+    let check_lines = props.check_lines.clone();
 
     // compile test file (it shoud have 'compile-flags:-g' in the header)
     let mut ProcRes = compile_test(config, props, testfile);
@@ -498,7 +498,7 @@ fn exec_compiled_test(config: &config, props: &TestProps,
                       testfile: &Path) -> ProcRes {
 
     // If testing the new runtime then set the RUST_NEWRT env var
-    let env = copy props.exec_env;
+    let env = props.exec_env.clone();
     let env = if config.newrt { env + &[(~"RUST_NEWRT", ~"1")] } else { env };
 
     match config.target {
@@ -742,7 +742,7 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
 
     // copy to target
     let copy_result = procsrv::run("", config.adb_path,
-        [~"push", copy args.prog, copy config.adb_test_dir],
+        [~"push", args.prog.clone(), config.adb_test_dir.clone()],
         ~[(~"",~"")], Some(~""));
 
     if config.verbose {
@@ -832,7 +832,7 @@ fn _arm_push_aux_shared_library(config: &config, testfile: &Path) {
         if (file.filetype() == Some(~".so")) {
 
             let copy_result = procsrv::run("", config.adb_path,
-                [~"push", file.to_str(), copy config.adb_test_dir],
+                [~"push", file.to_str(), config.adb_test_dir.clone()],
                 ~[(~"",~"")], Some(~""));
 
             if config.verbose {
diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs
index be9ab863942..054b4ce5177 100644
--- a/src/libextra/arc.rs
+++ b/src/libextra/arc.rs
@@ -534,7 +534,7 @@ mod tests {
 
             let arc_v : ARC<~[int]> = p.recv();
 
-            let v = copy (*arc_v.get());
+            let v = (*arc_v.get()).clone();
             assert_eq!(v[3], 4);
         };
 
diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs
index 3c1fc72e957..449a9aba4a7 100644
--- a/src/libextra/base64.rs
+++ b/src/libextra/base64.rs
@@ -211,14 +211,14 @@ impl<'self> FromBase64 for &'self [u8] {
             let val = byte as u32;
 
             match ch {
-                'A'..'Z'  => buf |= val - 0x41,
-                'a'..'z'  => buf |= val - 0x47,
-                '0'..'9'  => buf |= val + 0x04,
-                '+'|'-'   => buf |= 0x3E,
-                '/'|'_'   => buf |= 0x3F,
+                'A'..'Z' => buf |= val - 0x41,
+                'a'..'z' => buf |= val - 0x47,
+                '0'..'9' => buf |= val + 0x04,
+                '+'|'-' => buf |= 0x3E,
+                '/'|'_' => buf |= 0x3F,
                 '\r'|'\n' => loop,
-                '='       => break,
-                _         => return Err(~"Invalid Base64 character")
+                '=' => break,
+                _ => return Err(~"Invalid Base64 character")
             }
 
             buf <<= 6;
diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs
index 49cedac399e..f3f0f42125d 100644
--- a/src/libextra/bitv.rs
+++ b/src/libextra/bitv.rs
@@ -266,7 +266,7 @@ impl Bitv {
         else {
             let nelems = nbits/uint::bits +
                          if nbits % uint::bits == 0 {0} else {1};
-            let elem = if init {!0} else {0};
+            let elem = if init {!0u} else {0u};
             let s = vec::from_elem(nelems, elem);
             Big(~BigBitv::new(s))
         };
@@ -518,7 +518,7 @@ impl Clone for Bitv {
             Bitv{nbits: self.nbits, rep: Small(~SmallBitv{bits: b.bits})}
           }
           Big(ref b) => {
-            let mut st = vec::from_elem(self.nbits / uint::bits + 1, 0);
+            let mut st = vec::from_elem(self.nbits / uint::bits + 1, 0u);
             let len = st.len();
             for uint::range(0, len) |i| { st[i] = b.storage[i]; };
             Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: st})}
diff --git a/src/libextra/c_vec.rs b/src/libextra/c_vec.rs
index c6e7b5b0aa7..f72d3ee694f 100644
--- a/src/libextra/c_vec.rs
+++ b/src/libextra/c_vec.rs
@@ -119,9 +119,11 @@ pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: @fn())
  *
  * Fails if `ofs` is greater or equal to the length of the vector
  */
-pub fn get<T:Copy>(t: CVec<T>, ofs: uint) -> T {
+pub fn get<T:Clone>(t: CVec<T>, ofs: uint) -> T {
     assert!(ofs < len(t));
-    return unsafe { copy *ptr::mut_offset(t.base, ofs) };
+    return unsafe {
+        (*ptr::mut_offset(t.base, ofs)).clone()
+    };
 }
 
 /**
@@ -129,7 +131,7 @@ pub fn get<T:Copy>(t: CVec<T>, ofs: uint) -> T {
  *
  * Fails if `ofs` is greater or equal to the length of the vector
  */
-pub fn set<T:Copy>(t: CVec<T>, ofs: uint, v: T) {
+pub fn set<T>(t: CVec<T>, ofs: uint, v: T) {
     assert!(ofs < len(t));
     unsafe { *ptr::mut_offset(t.base, ofs) = v };
 }
diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs
index 35600df4f9d..840b4127577 100644
--- a/src/libextra/dlist.rs
+++ b/src/libextra/dlist.rs
@@ -609,8 +609,8 @@ mod tests {
     }
 
     #[cfg(test)]
-    fn list_from<T: Copy>(v: &[T]) -> DList<T> {
-        v.iter().transform(|x| copy *x).collect()
+    fn list_from<T: Clone>(v: &[T]) -> DList<T> {
+        v.iter().transform(|x| (*x).clone()).collect()
     }
 
     #[test]
diff --git a/src/libextra/ebml.rs b/src/libextra/ebml.rs
index 1ad44c5e28c..c9b0cbb2753 100644
--- a/src/libextra/ebml.rs
+++ b/src/libextra/ebml.rs
@@ -29,6 +29,7 @@ struct EbmlState {
     data_pos: uint,
 }
 
+#[deriving(Clone)]
 pub struct Doc {
     data: @~[u8],
     start: uint,
@@ -615,6 +616,7 @@ pub mod writer {
     use super::*;
 
     use std::cast;
+    use std::clone::Clone;
     use std::io;
 
     // ebml writing
@@ -623,6 +625,15 @@ pub mod writer {
         priv size_positions: ~[uint],
     }
 
+    impl Clone for Encoder {
+        fn clone(&self) -> Encoder {
+            Encoder {
+                writer: self.writer,
+                size_positions: self.size_positions.clone(),
+            }
+        }
+    }
+
     fn write_sized_vuint(w: @io::Writer, n: uint, size: uint) {
         match size {
             1u => w.write(&[0x80u8 | (n as u8)]),
diff --git a/src/libextra/fileinput.rs b/src/libextra/fileinput.rs
index 27c8051afac..cc87809ad5b 100644
--- a/src/libextra/fileinput.rs
+++ b/src/libextra/fileinput.rs
@@ -107,6 +107,7 @@ and `line_num_file` represent the number of lines read in total and in
 the current file respectively. `current_path` is `None` if the current
 file is `stdin`.
 */
+#[deriving(Clone)]
 pub struct FileInputState {
     current_path: Option<Path>,
     line_num: uint,
@@ -223,7 +224,7 @@ impl FileInput {
         let path_option = self.fi.files.shift();
         let file = match path_option {
             None => io::stdin(),
-            Some(ref path) => io::file_reader(path).get()
+            Some(ref path) => io::file_reader(path).unwrap()
         };
 
         self.fi.current_reader = Some(file);
@@ -259,7 +260,7 @@ impl FileInput {
     */
     pub fn each_line_state(&self,
                             f: &fn(&str, FileInputState) -> bool) -> bool {
-         self.each_line(|line| f(line, copy self.fi.state))
+         self.each_line(|line| f(line, self.fi.state.clone()))
     }
 
 
@@ -267,7 +268,7 @@ impl FileInput {
     Retrieve the current `FileInputState` information.
     */
     pub fn state(&self) -> FileInputState {
-        copy self.fi.state
+        self.fi.state.clone()
     }
 }
 
@@ -431,7 +432,7 @@ mod test {
         let paths = ~[Some(Path("some/path")),
                       Some(Path("some/other/path"))];
 
-        assert_eq!(pathify(strs, true), copy paths);
+        assert_eq!(pathify(strs, true), paths.clone());
         assert_eq!(pathify(strs, false), paths);
 
         assert_eq!(pathify([~"-"], true), ~[None]);
@@ -449,7 +450,7 @@ mod test {
             make_file(filename.get_ref(), [fmt!("%u", i)]);
         }
 
-        let fi = FileInput::from_vec(copy filenames);
+        let fi = FileInput::from_vec(filenames.clone());
 
         for "012".iter().enumerate().advance |(line, c)| {
             assert_eq!(fi.read_byte(), c as int);
@@ -459,7 +460,7 @@ mod test {
             assert_eq!(fi.state().line_num, line + 1);
             assert_eq!(fi.state().line_num_file, 1);
 
-            assert_eq!(copy fi.state().current_path, copy filenames[line]);
+            assert_eq!(fi.state().current_path.clone(), filenames[line].clone());
         }
 
         assert_eq!(fi.read_byte(), -1);
@@ -542,13 +543,13 @@ mod test {
         make_file(filenames[2].get_ref(), [~"3", ~"4"]);
 
         let mut count = 0;
-        for input_vec_state(copy filenames) |line, state| {
+        for input_vec_state(filenames.clone()) |line, state| {
             let expected_path = match line {
-                "1" | "2" => copy filenames[0],
-                "3" | "4" => copy filenames[2],
+                "1" | "2" => filenames[0].clone(),
+                "3" | "4" => filenames[2].clone(),
                 _ => fail!("unexpected line")
             };
-            assert_eq!(copy state.current_path, expected_path);
+            assert_eq!(state.current_path.clone(), expected_path);
             count += 1;
         }
         assert_eq!(count, 4);
diff --git a/src/libextra/flatpipes.rs b/src/libextra/flatpipes.rs
index 9ce7362ef71..5a5aacc8d54 100644
--- a/src/libextra/flatpipes.rs
+++ b/src/libextra/flatpipes.rs
@@ -164,8 +164,8 @@ Constructors for flat pipes that send POD types using memcpy.
 
 # Safety Note
 
-This module is currently unsafe because it uses `Copy Send` as a type
-parameter bounds meaning POD (plain old data), but `Copy Send` and
+This module is currently unsafe because it uses `Clone + Send` as a type
+parameter bounds meaning POD (plain old data), but `Clone + Send` and
 POD are not equivelant.
 
 */
@@ -188,7 +188,7 @@ pub mod pod {
     pub type PipeChan<T> = FlatChan<T, PodFlattener<T>, PipeByteChan>;
 
     /// Create a `FlatPort` from a `Reader`
-    pub fn reader_port<T:Copy + Send,R:Reader>(
+    pub fn reader_port<T:Clone + Send,R:Reader>(
         reader: R
     ) -> ReaderPort<T, R> {
         let unflat: PodUnflattener<T> = PodUnflattener::new();
@@ -197,7 +197,7 @@ pub mod pod {
     }
 
     /// Create a `FlatChan` from a `Writer`
-    pub fn writer_chan<T:Copy + Send,W:Writer>(
+    pub fn writer_chan<T:Clone + Send,W:Writer>(
         writer: W
     ) -> WriterChan<T, W> {
         let flat: PodFlattener<T> = PodFlattener::new();
@@ -206,21 +206,21 @@ pub mod pod {
     }
 
     /// Create a `FlatPort` from a `Port<~[u8]>`
-    pub fn pipe_port<T:Copy + Send>(port: Port<~[u8]>) -> PipePort<T> {
+    pub fn pipe_port<T:Clone + Send>(port: Port<~[u8]>) -> PipePort<T> {
         let unflat: PodUnflattener<T> = PodUnflattener::new();
         let byte_port = PipeBytePort::new(port);
         FlatPort::new(unflat, byte_port)
     }
 
     /// Create a `FlatChan` from a `Chan<~[u8]>`
-    pub fn pipe_chan<T:Copy + Send>(chan: Chan<~[u8]>) -> PipeChan<T> {
+    pub fn pipe_chan<T:Clone + Send>(chan: Chan<~[u8]>) -> PipeChan<T> {
         let flat: PodFlattener<T> = PodFlattener::new();
         let byte_chan = PipeByteChan::new(chan);
         FlatChan::new(flat, byte_chan)
     }
 
     /// Create a pair of `FlatChan` and `FlatPort`, backed by pipes
-    pub fn pipe_stream<T:Copy + Send>() -> (PipePort<T>, PipeChan<T>) {
+    pub fn pipe_stream<T:Clone + Send>() -> (PipePort<T>, PipeChan<T>) {
         let (port, chan) = comm::stream();
         return (pipe_port(port), pipe_chan(chan));
     }
@@ -348,7 +348,7 @@ pub mod flatteners {
     use std::sys::size_of;
     use std::vec;
 
-    // FIXME #4074: Copy + Send != POD
+    // FIXME #4074: Clone + Send != POD
     pub struct PodUnflattener<T> {
         bogus: ()
     }
@@ -357,17 +357,17 @@ pub mod flatteners {
         bogus: ()
     }
 
-    impl<T:Copy + Send> Unflattener<T> for PodUnflattener<T> {
+    impl<T:Clone + Send> Unflattener<T> for PodUnflattener<T> {
         fn unflatten(&self, buf: ~[u8]) -> T {
             assert!(size_of::<T>() != 0);
             assert_eq!(size_of::<T>(), buf.len());
             let addr_of_init: &u8 = unsafe { &*vec::raw::to_ptr(buf) };
             let addr_of_value: &T = unsafe { cast::transmute(addr_of_init) };
-            copy *addr_of_value
+            (*addr_of_value).clone()
         }
     }
 
-    impl<T:Copy + Send> Flattener<T> for PodFlattener<T> {
+    impl<T:Clone + Send> Flattener<T> for PodFlattener<T> {
         fn flatten(&self, val: T) -> ~[u8] {
             assert!(size_of::<T>() != 0);
             let val: *T = ptr::to_unsafe_ptr(&val);
@@ -376,7 +376,7 @@ pub mod flatteners {
         }
     }
 
-    impl<T:Copy + Send> PodUnflattener<T> {
+    impl<T:Clone + Send> PodUnflattener<T> {
         pub fn new() -> PodUnflattener<T> {
             PodUnflattener {
                 bogus: ()
@@ -384,7 +384,7 @@ pub mod flatteners {
         }
     }
 
-    impl<T:Copy + Send> PodFlattener<T> {
+    impl<T:Clone + Send> PodFlattener<T> {
         pub fn new() -> PodFlattener<T> {
             PodFlattener {
                 bogus: ()
@@ -655,7 +655,7 @@ mod test {
 
         chan.send(10);
 
-        let bytes = copy *chan.byte_chan.writer.bytes;
+        let bytes = (*chan.byte_chan.writer.bytes).clone();
 
         let reader = BufReader::new(bytes);
         let port = serial::reader_port(reader);
@@ -703,7 +703,7 @@ mod test {
 
         chan.send(10);
 
-        let bytes = copy *chan.byte_chan.writer.bytes;
+        let bytes = (*chan.byte_chan.writer.bytes).clone();
 
         let reader = BufReader::new(bytes);
         let port = pod::reader_port(reader);
@@ -785,13 +785,13 @@ mod test {
         let accept_chan = Cell::new(accept_chan);
 
         // The server task
-        let addr = copy addr0;
+        let addr = addr0.clone();
         do task::spawn || {
             let iotask = &uv::global_loop::get();
             let begin_connect_chan = begin_connect_chan.take();
             let accept_chan = accept_chan.take();
             let listen_res = do tcp::listen(
-                copy addr, port, 128, iotask, |_kill_ch| {
+                addr.clone(), port, 128, iotask, |_kill_ch| {
                     // Tell the sender to initiate the connection
                     debug!("listening");
                     begin_connect_chan.send(())
@@ -811,14 +811,14 @@ mod test {
         }
 
         // Client task
-        let addr = copy addr0;
+        let addr = addr0.clone();
         do task::spawn || {
             // Wait for the server to start listening
             begin_connect_port.recv();
 
             debug!("connecting");
             let iotask = &uv::global_loop::get();
-            let connect_result = tcp::connect(copy addr, port, iotask);
+            let connect_result = tcp::connect(addr.clone(), port, iotask);
             assert!(connect_result.is_ok());
             let sock = result::unwrap(connect_result);
             let socket_buf: tcp::TcpSocketBuf = tcp::socket_buf(sock);
diff --git a/src/libextra/fun_treemap.rs b/src/libextra/fun_treemap.rs
index 4461a4dba5f..7074d76536a 100644
--- a/src/libextra/fun_treemap.rs
+++ b/src/libextra/fun_treemap.rs
@@ -46,11 +46,11 @@ pub fn insert<K:Eq + Ord,V>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> {
 }
 
 /// Find a value based on the key
-pub fn find<K:Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K) -> Option<V> {
+pub fn find<K:Eq + Ord,V:Clone>(m: Treemap<K, V>, k: K) -> Option<V> {
     match *m {
         Empty => None,
         Node(kk, v, left, right) => cond!(
-            (k == *kk) { Some(copy *v)  }
+            (k == *kk) { Some((*v).clone()) }
             (k <  *kk) { find(left, k)  }
             _          { find(right, k) }
         )
@@ -58,7 +58,7 @@ pub fn find<K:Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K) -> Option<V> {
 }
 
 /// Visit all pairs in the map in order.
-pub fn traverse<K, V: Copy>(m: Treemap<K, V>, f: &fn(&K, &V)) {
+pub fn traverse<K, V>(m: Treemap<K, V>, f: &fn(&K, &V)) {
     match *m {
         Empty => (),
         // Previously, this had what looked like redundant
diff --git a/src/libextra/future.rs b/src/libextra/future.rs
index 3ef71e1731b..667f136276f 100644
--- a/src/libextra/future.rs
+++ b/src/libextra/future.rs
@@ -53,10 +53,10 @@ priv enum FutureState<A> {
 }
 
 /// Methods on the `future` type
-impl<A:Copy> Future<A> {
+impl<A:Clone> Future<A> {
     pub fn get(&mut self) -> A {
         //! Get the value of the future.
-        copy *(self.get_ref())
+        (*(self.get_ref())).clone()
     }
 }
 
diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs
index f8119143c61..07a1c674404 100644
--- a/src/libextra/getopts.rs
+++ b/src/libextra/getopts.rs
@@ -52,7 +52,7 @@
  *    fn main() {
  *        let args = os::args();
  *
- *        let program = copy args[0];
+ *        let program = args[0].clone();
  *
  *        let opts = ~[
  *            optopt("o"),
@@ -69,7 +69,7 @@
  *        }
  *        let output = opt_maybe_str(&matches, "o");
  *        let input: &str = if !matches.free.is_empty() {
- *            copy matches.free[0]
+ *            matches.free[0].clone()
  *        } else {
  *            print_usage(program, opts);
  *            return;
@@ -89,20 +89,28 @@ use std::option::{Some, None};
 use std::str;
 use std::vec;
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum Name {
     Long(~str),
     Short(char),
 }
 
-#[deriving(Eq)]
-pub enum HasArg { Yes, No, Maybe, }
+#[deriving(Clone, Eq)]
+pub enum HasArg {
+    Yes,
+    No,
+    Maybe,
+}
 
-#[deriving(Eq)]
-pub enum Occur { Req, Optional, Multi, }
+#[deriving(Clone, Eq)]
+pub enum Occur {
+    Req,
+    Optional,
+    Multi,
+}
 
 /// A description of a possible option
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct Opt {
     name: Name,
     hasarg: HasArg,
@@ -150,14 +158,17 @@ pub fn optmulti(name: &str) -> Opt {
     return Opt {name: mkname(name), hasarg: Yes, occur: Multi};
 }
 
-#[deriving(Eq)]
-enum Optval { Val(~str), Given, }
+#[deriving(Clone, Eq)]
+enum Optval {
+    Val(~str),
+    Given,
+}
 
 /**
  * The result of checking command line arguments. Contains a vector
  * of matches and a vector of free strings.
  */
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct Matches {
     opts: ~[Opt],
     vals: ~[~[Optval]],
@@ -171,7 +182,7 @@ fn is_arg(arg: &str) -> bool {
 fn name_str(nm: &Name) -> ~str {
     return match *nm {
       Short(ch) => str::from_char(ch),
-      Long(ref s) => copy *s
+      Long(ref s) => (*s).clone()
     };
 }
 
@@ -183,7 +194,7 @@ fn find_opt(opts: &[Opt], nm: Name) -> Option<uint> {
  * The type returned when the command line does not conform to the
  * expected format. Pass this value to <fail_str> to get an error message.
  */
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum Fail_ {
     ArgumentMissing(~str),
     UnrecognizedOption(~str),
@@ -234,13 +245,13 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
     let l = args.len();
     let mut i = 0;
     while i < l {
-        let cur = copy args[i];
+        let cur = args[i].clone();
         let curlen = cur.len();
         if !is_arg(cur) {
             free.push(cur);
         } else if cur == ~"--" {
             let mut j = i + 1;
-            while j < l { free.push(copy args[j]); j += 1; }
+            while j < l { free.push(args[j].clone()); j += 1; }
             break;
         } else {
             let mut names;
@@ -270,7 +281,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
                        interpreted correctly
                     */
 
-                    match find_opt(opts, copy opt) {
+                    match find_opt(opts, opt.clone()) {
                       Some(id) => last_valid_opt_id = Some(id),
                       None => {
                         let arg_follows =
@@ -296,7 +307,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
             let mut name_pos = 0;
             for names.iter().advance() |nm| {
                 name_pos += 1;
-                let optid = match find_opt(opts, copy *nm) {
+                let optid = match find_opt(opts, (*nm).clone()) {
                   Some(id) => id,
                   None => return Err(UnrecognizedOption(name_str(nm)))
                 };
@@ -309,18 +320,18 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
                   }
                   Maybe => {
                     if !i_arg.is_none() {
-                        vals[optid].push(Val((copy i_arg).get()));
+                        vals[optid].push(Val((i_arg.clone()).get()));
                     } else if name_pos < names.len() ||
                                   i + 1 == l || is_arg(args[i + 1]) {
                         vals[optid].push(Given);
-                    } else { i += 1; vals[optid].push(Val(copy args[i])); }
+                    } else { i += 1; vals[optid].push(Val(args[i].clone())); }
                   }
                   Yes => {
                     if !i_arg.is_none() {
-                        vals[optid].push(Val((copy i_arg).get()));
+                        vals[optid].push(Val(i_arg.clone().get()));
                     } else if i + 1 == l {
                         return Err(ArgumentMissing(name_str(nm)));
-                    } else { i += 1; vals[optid].push(Val(copy args[i])); }
+                    } else { i += 1; vals[optid].push(Val(args[i].clone())); }
                   }
                 }
             }
@@ -350,7 +361,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
 
 fn opt_vals(mm: &Matches, nm: &str) -> ~[Optval] {
     return match find_opt(mm.opts, mkname(nm)) {
-      Some(id) => copy mm.vals[id],
+      Some(id) => mm.vals[id].clone(),
       None => {
         error!("No option '%s' defined", nm);
         fail!()
@@ -358,7 +369,7 @@ fn opt_vals(mm: &Matches, nm: &str) -> ~[Optval] {
     };
 }
 
-fn opt_val(mm: &Matches, nm: &str) -> Optval { copy opt_vals(mm, nm)[0] }
+fn opt_val(mm: &Matches, nm: &str) -> Optval { opt_vals(mm, nm)[0].clone() }
 
 /// Returns true if an option was matched
 pub fn opt_present(mm: &Matches, nm: &str) -> bool {
@@ -401,7 +412,7 @@ pub fn opt_str(mm: &Matches, nm: &str) -> ~str {
 pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str {
     for names.iter().advance |nm| {
         match opt_val(mm, *nm) {
-          Val(ref s) => return copy *s,
+          Val(ref s) => return (*s).clone(),
           _ => ()
         }
     }
@@ -419,7 +430,7 @@ pub fn opt_strs(mm: &Matches, nm: &str) -> ~[~str] {
     let mut acc: ~[~str] = ~[];
     let r = opt_vals(mm, nm);
     for r.iter().advance |v| {
-        match *v { Val(ref s) => acc.push(copy *s), _ => () }
+        match *v { Val(ref s) => acc.push((*s).clone()), _ => () }
     }
     acc
 }
@@ -429,7 +440,7 @@ pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> {
     let vals = opt_vals(mm, nm);
     if vals.is_empty() { return None::<~str>; }
     return match vals[0] {
-        Val(ref s) => Some(copy *s),
+        Val(ref s) => Some((*s).clone()),
         _ => None
     };
 }
@@ -445,7 +456,7 @@ pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> {
 pub fn opt_default(mm: &Matches, nm: &str, def: &str) -> Option<~str> {
     let vals = opt_vals(mm, nm);
     if vals.is_empty() { return None::<~str>; }
-    return match vals[0] { Val(ref s) => Some::<~str>(copy *s),
+    return match vals[0] { Val(ref s) => Some::<~str>((*s).clone()),
                            _      => Some::<~str>(str::to_owned(def)) }
 }
 
@@ -471,7 +482,7 @@ pub mod groups {
     /** one group of options, e.g., both -h and --help, along with
      * their shared description and properties
      */
-    #[deriving(Eq)]
+    #[deriving(Clone, Eq)]
     pub struct OptGroup {
         short_name: ~str,
         long_name: ~str,
@@ -556,7 +567,7 @@ pub mod groups {
                      long_name: long_name,
                      hasarg: hasarg,
                      occur: occur,
-                     _} = copy *lopt;
+                     _} = (*lopt).clone();
 
         match (short_name.len(), long_name.len()) {
            (0,0) => fail!("this long-format option was given no name"),
@@ -600,7 +611,7 @@ pub mod groups {
                          hint: hint,
                          desc: desc,
                          hasarg: hasarg,
-                         _} = copy *optref;
+                         _} = (*optref).clone();
 
             let mut row = " ".repeat(4);
 
@@ -916,7 +927,7 @@ mod tests {
         let rs = getopts(args, opts);
         match rs {
           Err(f) => {
-            error!(fail_str(copy f));
+            error!(fail_str(f.clone()));
             check_fail_type(f, UnexpectedArgument_);
           }
           _ => fail!()
diff --git a/src/libextra/json.rs b/src/libextra/json.rs
index 00b172dda03..8c5af33cc38 100644
--- a/src/libextra/json.rs
+++ b/src/libextra/json.rs
@@ -30,6 +30,7 @@ use sort::Sort;
 use treemap::TreeMap;
 
 /// Represents a json value
+#[deriving(Clone, Eq)]
 pub enum Json {
     Number(float),
     String(~str),
@@ -1113,43 +1114,6 @@ impl serialize::Decoder for Decoder {
     }
 }
 
-impl Eq for Json {
-    fn eq(&self, other: &Json) -> bool {
-        match (self) {
-            &Number(f0) =>
-                match other { &Number(f1) => f0 == f1, _ => false },
-            &String(ref s0) =>
-                match other { &String(ref s1) => s0 == s1, _ => false },
-            &Boolean(b0) =>
-                match other { &Boolean(b1) => b0 == b1, _ => false },
-            &Null =>
-                match other { &Null => true, _ => false },
-            &List(ref v0) =>
-                match other { &List(ref v1) => v0 == v1, _ => false },
-            &Object(ref d0) => {
-                match other {
-                    &Object(ref d1) => {
-                        if d0.len() == d1.len() {
-                            let mut equal = true;
-                            for d0.iter().advance |(k, v0)| {
-                                match d1.find(k) {
-                                    Some(v1) if v0 == v1 => { },
-                                    _ => { equal = false; break }
-                                }
-                            };
-                            equal
-                        } else {
-                            false
-                        }
-                    }
-                    _ => false
-                }
-            }
-        }
-    }
-    fn ne(&self, other: &Json) -> bool { !self.eq(other) }
-}
-
 /// Test if two json values are less than one another
 impl Ord for Json {
     fn lt(&self, other: &Json) -> bool {
@@ -1195,12 +1159,12 @@ impl Ord for Json {
 
                         // FIXME #4430: this is horribly inefficient...
                         for d0.iter().advance |(k, v)| {
-                             d0_flat.push((@copy *k, @copy *v));
+                             d0_flat.push((@(*k).clone(), @(*v).clone()));
                         }
                         d0_flat.qsort();
 
                         for d1.iter().advance |(k, v)| {
-                            d1_flat.push((@copy *k, @copy *v));
+                            d1_flat.push((@(*k).clone(), @(*v).clone()));
                         }
                         d1_flat.qsort();
 
@@ -1232,7 +1196,7 @@ pub trait ToJson {
 }
 
 impl ToJson for Json {
-    fn to_json(&self) -> Json { copy *self }
+    fn to_json(&self) -> Json { (*self).clone() }
 }
 
 impl ToJson for @Json {
@@ -1300,11 +1264,11 @@ impl ToJson for bool {
 }
 
 impl ToJson for ~str {
-    fn to_json(&self) -> Json { String(copy *self) }
+    fn to_json(&self) -> Json { String((*self).clone()) }
 }
 
 impl ToJson for @~str {
-    fn to_json(&self) -> Json { String(copy **self) }
+    fn to_json(&self) -> Json { String((**self).clone()) }
 }
 
 impl<A:ToJson,B:ToJson> ToJson for (A, B) {
@@ -1335,7 +1299,7 @@ impl<A:ToJson> ToJson for HashMap<~str, A> {
     fn to_json(&self) -> Json {
         let mut d = HashMap::new();
         for self.iter().advance |(key, value)| {
-            d.insert(copy *key, value.to_json());
+            d.insert((*key).clone(), value.to_json());
         }
         Object(~d)
     }
@@ -1345,7 +1309,7 @@ impl<A:ToJson> ToJson for TreeMap<~str, A> {
     fn to_json(&self) -> Json {
         let mut d = HashMap::new();
         for self.iter().advance |(key, value)| {
-            d.insert(copy *key, value.to_json());
+            d.insert((*key).clone(), value.to_json());
         }
         Object(~d)
     }
@@ -1404,7 +1368,7 @@ mod tests {
 
         for items.iter().advance |item| {
             match *item {
-                (ref key, ref value) => { d.insert(copy *key, copy *value); },
+                (ref key, ref value) => { d.insert((*key).clone(), (*value).clone()); },
             }
         };
 
@@ -1549,8 +1513,8 @@ mod tests {
 
         // We can't compare the strings directly because the object fields be
         // printed in a different order.
-        assert_eq!(copy a, from_str(to_str(&a)).unwrap());
-        assert_eq!(copy a, from_str(to_pretty_str(&a)).unwrap());
+        assert_eq!(a.clone(), from_str(to_str(&a)).unwrap());
+        assert_eq!(a.clone(), from_str(to_pretty_str(&a)).unwrap());
     }
 
     #[test]
diff --git a/src/libextra/list.rs b/src/libextra/list.rs
index 86b01cf157d..87d0c05aec1 100644
--- a/src/libextra/list.rs
+++ b/src/libextra/list.rs
@@ -25,8 +25,8 @@ pub enum MutList<T> {
 }
 
 /// Create a list from a vector
-pub fn from_vec<T:Copy>(v: &[T]) -> @List<T> {
-    v.rev_iter().fold(@Nil::<T>, |t, h| @Cons(copy *h, t))
+pub fn from_vec<T:Clone>(v: &[T]) -> @List<T> {
+    v.rev_iter().fold(@Nil::<T>, |t, h| @Cons((*h).clone(), t))
 }
 
 /**
@@ -42,7 +42,7 @@ pub fn from_vec<T:Copy>(v: &[T]) -> @List<T> {
  * * z - The initial value
  * * f - The function to apply
  */
-pub fn foldl<T:Copy,U>(z: T, ls: @List<U>, f: &fn(&T, &U) -> T) -> T {
+pub fn foldl<T:Clone,U>(z: T, ls: @List<U>, f: &fn(&T, &U) -> T) -> T {
     let mut accum: T = z;
     do iter(ls) |elt| { accum = f(&accum, elt);}
     accum
@@ -55,12 +55,12 @@ pub fn foldl<T:Copy,U>(z: T, ls: @List<U>, f: &fn(&T, &U) -> T) -> T {
  * When function `f` returns true then an option containing the element
  * is returned. If `f` matches no elements then none is returned.
  */
-pub fn find<T:Copy>(ls: @List<T>, f: &fn(&T) -> bool) -> Option<T> {
+pub fn find<T:Clone>(ls: @List<T>, f: &fn(&T) -> bool) -> Option<T> {
     let mut ls = ls;
     loop {
         ls = match *ls {
           Cons(ref hd, tl) => {
-            if f(hd) { return Some(copy *hd); }
+            if f(hd) { return Some((*hd).clone()); }
             tl
           }
           Nil => return None
@@ -69,7 +69,7 @@ pub fn find<T:Copy>(ls: @List<T>, f: &fn(&T) -> bool) -> Option<T> {
 }
 
 /// Returns true if a list contains an element with the given value
-pub fn has<T:Copy + Eq>(ls: @List<T>, elt: T) -> bool {
+pub fn has<T:Eq>(ls: @List<T>, elt: T) -> bool {
     for each(ls) |e| {
         if *e == elt { return true; }
     }
@@ -77,7 +77,7 @@ pub fn has<T:Copy + Eq>(ls: @List<T>, elt: T) -> bool {
 }
 
 /// Returns true if the list is empty
-pub fn is_empty<T:Copy>(ls: @List<T>) -> bool {
+pub fn is_empty<T>(ls: @List<T>) -> bool {
     match *ls {
         Nil => true,
         _ => false
@@ -92,7 +92,7 @@ pub fn len<T>(ls: @List<T>) -> uint {
 }
 
 /// Returns all but the first element of a list
-pub fn tail<T:Copy>(ls: @List<T>) -> @List<T> {
+pub fn tail<T>(ls: @List<T>) -> @List<T> {
     match *ls {
         Cons(_, tl) => return tl,
         Nil => fail!("list empty")
@@ -100,21 +100,21 @@ pub fn tail<T:Copy>(ls: @List<T>) -> @List<T> {
 }
 
 /// Returns the first element of a list
-pub fn head<T:Copy>(ls: @List<T>) -> T {
+pub fn head<T:Clone>(ls: @List<T>) -> T {
     match *ls {
-      Cons(ref hd, _) => copy *hd,
+      Cons(ref hd, _) => (*hd).clone(),
       // makes me sad
       _ => fail!("head invoked on empty list")
     }
 }
 
 /// Appends one list to another
-pub fn append<T:Copy>(l: @List<T>, m: @List<T>) -> @List<T> {
+pub fn append<T:Clone>(l: @List<T>, m: @List<T>) -> @List<T> {
     match *l {
       Nil => return m,
       Cons(ref x, xs) => {
         let rest = append(xs, m);
-        return @Cons(copy *x, rest);
+        return @Cons((*x).clone(), rest);
       }
     }
 }
@@ -122,7 +122,7 @@ pub fn append<T:Copy>(l: @List<T>, m: @List<T>) -> @List<T> {
 /*
 /// Push one element into the front of a list, returning a new list
 /// THIS VERSION DOESN'T ACTUALLY WORK
-fn push<T:Copy>(ll: &mut @list<T>, vv: T) {
+fn push<T:Clone>(ll: &mut @list<T>, vv: T) {
     ll = &mut @cons(vv, *ll)
 }
 */
diff --git a/src/libextra/net/ip.rs b/src/libextra/net/ip.rs
index f6516fad6b8..4c3fefc6eed 100644
--- a/src/libextra/net/ip.rs
+++ b/src/libextra/net/ip.rs
@@ -176,12 +176,19 @@ pub mod v4 {
     pub fn parse_addr(ip: &str) -> IpAddr {
         match try_parse_addr(ip) {
           result::Ok(addr) => addr,
-          result::Err(ref err_data) => fail!(copy err_data.err_msg)
+          result::Err(ref err_data) => fail!(err_data.err_msg.clone())
         }
     }
+
     // the simple, old style numberic representation of
     // ipv4
-    pub struct Ipv4Rep { a: u8, b: u8, c: u8, d: u8 }
+    #[deriving(Clone)]
+    pub struct Ipv4Rep {
+        a: u8,
+        b: u8,
+        c: u8,
+        d: u8,
+    }
 
     pub trait AsUnsafeU32 {
         unsafe fn as_u32(&self) -> u32;
@@ -271,7 +278,7 @@ pub mod v6 {
     pub fn parse_addr(ip: &str) -> IpAddr {
         match try_parse_addr(ip) {
           result::Ok(addr) => addr,
-          result::Err(err_data) => fail!(copy err_data.err_msg)
+          result::Err(err_data) => fail!(err_data.err_msg.clone())
         }
     }
     pub fn try_parse_addr(ip: &str) -> result::Result<IpAddr,ParseAddrErr> {
diff --git a/src/libextra/net/tcp.rs b/src/libextra/net/tcp.rs
index d262304298d..eebb8490aa2 100644
--- a/src/libextra/net/tcp.rs
+++ b/src/libextra/net/tcp.rs
@@ -86,6 +86,7 @@ pub fn TcpSocketBuf(data: @mut TcpBufferedSocketData) -> TcpSocketBuf {
 }
 
 /// Contains raw, string-based, error information returned from libuv
+#[deriving(Clone)]
 pub struct TcpErrData {
     err_name: ~str,
     err_msg: ~str,
@@ -278,8 +279,8 @@ pub fn connect(input_ip: ip::IpAddr, port: uint,
                                                     as *libc::c_void);
                 let tcp_conn_err = match err_data.err_name {
                     ~"ECONNREFUSED" => ConnectionRefused,
-                    _ => GenericConnectErr(copy err_data.err_name,
-                                           copy err_data.err_msg)
+                    _ => GenericConnectErr(err_data.err_name.clone(),
+                                           err_data.err_msg.clone())
                 };
                 result::Err(tcp_conn_err)
             }
@@ -343,7 +344,7 @@ pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8])
 {
     let socket_data_ptr: *TcpSocketData = &*sock.socket_data;
     do future_spawn {
-        let data_copy = copy(raw_write_data);
+        let data_copy = raw_write_data.clone();
         write_common_impl(socket_data_ptr, data_copy)
     }
 }
@@ -770,8 +771,8 @@ fn listen_common(host_ip: ip::IpAddr,
                     debug!("Got '%s' '%s' libuv error",
                                     err_data.err_name, err_data.err_msg);
                     result::Err(
-                        GenericListenErr(copy err_data.err_name,
-                                         copy err_data.err_msg))
+                        GenericListenErr(err_data.err_name.clone(),
+                                         err_data.err_msg.clone()))
                 }
             }
         }
@@ -791,8 +792,8 @@ fn listen_common(host_ip: ip::IpAddr,
             match kill_result {
                 // some failure post bind/listen
                 Some(ref err_data) => result::Err(GenericListenErr(
-                    copy err_data.err_name,
-                    copy err_data.err_msg)),
+                    err_data.err_name.clone(),
+                    err_data.err_msg.clone())),
                 // clean exit
                 None => result::Ok(())
             }
@@ -1263,7 +1264,10 @@ trait ToTcpErr {
 
 impl ToTcpErr for uv::ll::uv_err_data {
     fn to_tcp_err(&self) -> TcpErrData {
-        TcpErrData { err_name: copy self.err_name, err_msg: copy self.err_msg }
+        TcpErrData {
+            err_name: self.err_name.clone(),
+            err_msg: self.err_msg.clone(),
+        }
     }
 }
 
diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs
index 4bc77f313df..9404f3f4896 100644
--- a/src/libextra/num/bigint.rs
+++ b/src/libextra/num/bigint.rs
@@ -282,7 +282,7 @@ impl Mul<BigUint, BigUint> for BigUint {
 
         fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint {
             if n == 0 { return Zero::zero(); }
-            if n == 1 { return copy *a; }
+            if n == 1 { return (*a).clone(); }
 
             let mut carry = 0;
             let mut prod = do a.data.iter().transform |ai| {
@@ -357,10 +357,10 @@ impl Integer for BigUint {
     fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) {
         if other.is_zero() { fail!() }
         if self.is_zero() { return (Zero::zero(), Zero::zero()); }
-        if *other == One::one() { return (copy *self, Zero::zero()); }
+        if *other == One::one() { return ((*self).clone(), Zero::zero()); }
 
         match self.cmp(other) {
-            Less    => return (Zero::zero(), copy *self),
+            Less    => return (Zero::zero(), (*self).clone()),
             Equal   => return (One::one(), Zero::zero()),
             Greater => {} // Do nothing
         }
@@ -411,7 +411,7 @@ impl Integer for BigUint {
         fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
             -> (BigUint, BigUint, BigUint) {
             if a.data.len() < n {
-                return (Zero::zero(), Zero::zero(), copy *a);
+                return (Zero::zero(), Zero::zero(), (*a).clone());
             }
 
             let an = a.data.slice(a.data.len() - n, a.data.len());
@@ -428,7 +428,7 @@ impl Integer for BigUint {
 
             let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
             if shift == 0 {
-                return (BigUint::new(d), One::one(), copy *b);
+                return (BigUint::new(d), One::one(), (*b).clone());
             }
             return (BigUint::from_slice(d).shl_unit(shift),
                     One::one::<BigUint>().shl_unit(shift),
@@ -444,8 +444,8 @@ impl Integer for BigUint {
 
     fn gcd(&self, other: &BigUint) -> BigUint {
         // Use Euclid's algorithm
-        let mut m = copy *self;
-        let mut n = copy *other;
+        let mut m = (*self).clone();
+        let mut n = (*other).clone();
         while !m.is_zero() {
             let temp = m;
             m = n % temp;
@@ -500,7 +500,7 @@ impl ToStrRadix for BigUint {
         if base == BigDigit::base {
             return fill_concat(self.data, radix, max_len)
         }
-        return fill_concat(convert_base(copy *self, base), radix, max_len);
+        return fill_concat(convert_base((*self).clone(), base), radix, max_len);
 
 
         fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
@@ -612,14 +612,14 @@ impl BigUint {
 
 
     priv fn shl_unit(&self, n_unit: uint) -> BigUint {
-        if n_unit == 0 || self.is_zero() { return copy *self; }
+        if n_unit == 0 || self.is_zero() { return (*self).clone(); }
 
-        return BigUint::new(vec::from_elem(n_unit, 0) + self.data);
+        return BigUint::new(vec::from_elem(n_unit, 0u32) + self.data);
     }
 
 
     priv fn shl_bits(&self, n_bits: uint) -> BigUint {
-        if n_bits == 0 || self.is_zero() { return copy *self; }
+        if n_bits == 0 || self.is_zero() { return (*self).clone(); }
 
         let mut carry = 0;
         let mut shifted = do self.data.iter().transform |elem| {
@@ -635,7 +635,7 @@ impl BigUint {
 
 
     priv fn shr_unit(&self, n_unit: uint) -> BigUint {
-        if n_unit == 0 { return copy *self; }
+        if n_unit == 0 { return (*self).clone(); }
         if self.data.len() < n_unit { return Zero::zero(); }
         return BigUint::from_slice(
             self.data.slice(n_unit, self.data.len())
@@ -644,7 +644,7 @@ impl BigUint {
 
 
     priv fn shr_bits(&self, n_bits: uint) -> BigUint {
-        if n_bits == 0 || self.data.is_empty() { return copy *self; }
+        if n_bits == 0 || self.data.is_empty() { return (*self).clone(); }
 
         let mut borrow = 0;
         let mut shifted = ~[];
diff --git a/src/libextra/par.rs b/src/libextra/par.rs
index 8023fe2c5da..1c686843ab0 100644
--- a/src/libextra/par.rs
+++ b/src/libextra/par.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Cloneright 2012 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -32,7 +32,7 @@ static MIN_GRANULARITY : uint = 1024u;
  * This is used to build most of the other parallel vector functions,
  * like map or alli.
  */
-fn map_slices<A:Copy + Send,B:Copy + Send>(
+fn map_slices<A:Clone + Send,B:Clone + Send>(
     xs: &[A],
     f: &fn() -> ~fn(uint, v: &[A]) -> B)
     -> ~[B] {
@@ -42,8 +42,7 @@ fn map_slices<A:Copy + Send,B:Copy + Send>(
         info!("small slice");
         // This is a small vector, fall back on the normal map.
         ~[f()(0u, xs)]
-    }
-    else {
+    } else {
         let num_tasks = num::min(MAX_TASKS, len / MIN_GRANULARITY);
 
         let items_per_task = len / num_tasks;
@@ -86,7 +85,7 @@ fn map_slices<A:Copy + Send,B:Copy + Send>(
 }
 
 /// A parallel version of map.
-pub fn map<A:Copy + Send,B:Copy + Send>(
+pub fn map<A:Copy + Clone + Send,B:Copy + Clone + Send>(
     xs: &[A], fn_factory: &fn() -> ~fn(&A) -> B) -> ~[B] {
     vec::concat(map_slices(xs, || {
         let f = fn_factory();
@@ -97,7 +96,7 @@ pub fn map<A:Copy + Send,B:Copy + Send>(
 }
 
 /// A parallel version of mapi.
-pub fn mapi<A:Copy + Send,B:Copy + Send>(
+pub fn mapi<A:Copy + Clone + Send,B:Copy + Clone + Send>(
         xs: &[A],
         fn_factory: &fn() -> ~fn(uint, &A) -> B) -> ~[B] {
     let slices = map_slices(xs, || {
@@ -116,7 +115,7 @@ pub fn mapi<A:Copy + Send,B:Copy + Send>(
 }
 
 /// Returns true if the function holds for all elements in the vector.
-pub fn alli<A:Copy + Send>(
+pub fn alli<A:Clone + Send>(
     xs: &[A],
     fn_factory: &fn() -> ~fn(uint, &A) -> bool) -> bool
 {
@@ -131,7 +130,7 @@ pub fn alli<A:Copy + Send>(
 }
 
 /// Returns true if the function holds for any elements in the vector.
-pub fn any<A:Copy + Send>(
+pub fn any<A:Clone + Send>(
     xs: &[A],
     fn_factory: &fn() -> ~fn(&A) -> bool) -> bool {
     let mapped = map_slices(xs, || {
diff --git a/src/libextra/priority_queue.rs b/src/libextra/priority_queue.rs
index 58bf4ba9247..dc274dfb814 100644
--- a/src/libextra/priority_queue.rs
+++ b/src/libextra/priority_queue.rs
@@ -308,8 +308,8 @@ mod tests {
     }
 
     fn check_to_vec(data: ~[int]) {
-        let heap = PriorityQueue::from_vec(copy data);
-        assert_eq!(merge_sort((copy heap).to_vec(), |x, y| x.le(y)),
+        let heap = PriorityQueue::from_vec(data.clone());
+        assert_eq!(merge_sort(heap.clone().to_vec(), |x, y| x.le(y)),
                    merge_sort(data, |x, y| x.le(y)));
         assert_eq!(heap.to_sorted_vec(), merge_sort(data, |x, y| x.le(y)));
     }
diff --git a/src/libextra/ringbuf.rs b/src/libextra/ringbuf.rs
index feec954bc02..c331cdfd868 100644
--- a/src/libextra/ringbuf.rs
+++ b/src/libextra/ringbuf.rs
@@ -329,8 +329,8 @@ impl<A, T: Iterator<A>> FromIterator<A, T> for RingBuf<A> {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use std::clone::Clone;
     use std::cmp::Eq;
-    use std::kinds::Copy;
     use std::{int, uint};
     use extra::test;
 
@@ -416,34 +416,34 @@ mod tests {
     }
 
     #[cfg(test)]
-    fn test_parameterized<T:Copy + Eq>(a: T, b: T, c: T, d: T) {
-        let mut deq = RingBuf::new();
+    fn test_parameterized<T:Clone + Eq>(a: T, b: T, c: T, d: T) {
+        let mut deq = Deque::new();
         assert_eq!(deq.len(), 0);
-        deq.push_front(copy a);
-        deq.push_front(copy b);
-        deq.push_back(copy c);
+        deq.add_front(a.clone());
+        deq.add_front(b.clone());
+        deq.add_back(c.clone());
         assert_eq!(deq.len(), 3);
-        deq.push_back(copy d);
+        deq.add_back(d.clone());
         assert_eq!(deq.len(), 4);
-        assert_eq!(deq.front(), Some(&b));
-        assert_eq!(deq.back(), Some(&d));
-        assert_eq!(deq.pop_front(), Some(copy b));
-        assert_eq!(deq.pop_back(), Some(copy d));
-        assert_eq!(deq.pop_back(), Some(copy c));
-        assert_eq!(deq.pop_back(), Some(copy a));
+        assert_eq!((*deq.peek_front()).clone(), b.clone());
+        assert_eq!((*deq.peek_back()).clone(), d.clone());
+        assert_eq!(deq.pop_front(), b.clone());
+        assert_eq!(deq.pop_back(), d.clone());
+        assert_eq!(deq.pop_back(), c.clone());
+        assert_eq!(deq.pop_back(), a.clone());
         assert_eq!(deq.len(), 0);
-        deq.push_back(copy c);
+        deq.add_back(c.clone());
         assert_eq!(deq.len(), 1);
-        deq.push_front(copy b);
+        deq.add_front(b.clone());
         assert_eq!(deq.len(), 2);
-        deq.push_back(copy d);
+        deq.add_back(d.clone());
         assert_eq!(deq.len(), 3);
-        deq.push_front(copy a);
+        deq.add_front(a.clone());
         assert_eq!(deq.len(), 4);
-        assert_eq!(copy *deq.get(0), copy a);
-        assert_eq!(copy *deq.get(1), copy b);
-        assert_eq!(copy *deq.get(2), copy c);
-        assert_eq!(copy *deq.get(3), copy d);
+        assert_eq!((*deq.get(0)).clone(), a.clone());
+        assert_eq!((*deq.get(1)).clone(), b.clone());
+        assert_eq!((*deq.get(2)).clone(), c.clone());
+        assert_eq!((*deq.get(3)).clone(), d.clone());
     }
 
     #[test]
@@ -501,15 +501,21 @@ mod tests {
         }
     }
 
-    #[deriving(Eq)]
-    enum Taggy { One(int), Two(int, int), Three(int, int, int), }
+    #[deriving(Clone, Eq)]
+    enum Taggy {
+        One(int),
+        Two(int, int),
+        Three(int, int, int),
+    }
 
-    #[deriving(Eq)]
+    #[deriving(Clone, Eq)]
     enum Taggypar<T> {
-        Onepar(int), Twopar(int, int), Threepar(int, int, int),
+        Onepar(int),
+        Twopar(int, int),
+        Threepar(int, int, int),
     }
 
-    #[deriving(Eq)]
+    #[deriving(Clone, Eq)]
     struct RecCy {
         x: int,
         y: int,
diff --git a/src/libextra/semver.rs b/src/libextra/semver.rs
index dc016c8117b..9f2bfd6592a 100644
--- a/src/libextra/semver.rs
+++ b/src/libextra/semver.rs
@@ -21,7 +21,7 @@ use std::option::{Option, Some, None};
 use std::to_str::ToStr;
 use std::uint;
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum Identifier {
     Numeric(uint),
     AlphaNumeric(~str)
@@ -62,7 +62,7 @@ impl ToStr for Identifier {
 }
 
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct Version {
     major: uint,
     minor: uint,
diff --git a/src/libextra/smallintmap.rs b/src/libextra/smallintmap.rs
index 200e8242094..6ad4d2acd90 100644
--- a/src/libextra/smallintmap.rs
+++ b/src/libextra/smallintmap.rs
@@ -219,12 +219,12 @@ impl<V> SmallIntMap<V> {
     }
 }
 
-impl<V:Copy> SmallIntMap<V> {
+impl<V:Clone> SmallIntMap<V> {
     pub fn update_with_key(&mut self, key: uint, val: V,
                            ff: &fn(uint, V, V) -> V) -> bool {
         let new_val = match self.find(&key) {
             None => val,
-            Some(orig) => ff(key, copy *orig, val)
+            Some(orig) => ff(key, (*orig).clone(), val)
         };
         self.insert(key, new_val)
     }
diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs
index db4ad43e41d..8a21ea0bd3b 100644
--- a/src/libextra/sort.rs
+++ b/src/libextra/sort.rs
@@ -24,19 +24,18 @@ type Le<'self, T> = &'self fn(v1: &T, v2: &T) -> bool;
  * Has worst case O(n log n) performance, best case O(n), but
  * is not space efficient. This is a stable sort.
  */
-pub fn merge_sort<T:Copy>(v: &[T], le: Le<T>) -> ~[T] {
+pub fn merge_sort<T:Copy + Clone>(v: &[T], le: Le<T>) -> ~[T] {
     type Slice = (uint, uint);
 
     return merge_sort_(v, (0u, v.len()), le);
 
-    fn merge_sort_<T:Copy>(v: &[T], slice: Slice, le: Le<T>)
-        -> ~[T] {
+    fn merge_sort_<T:Copy + Clone>(v: &[T], slice: Slice, le: Le<T>) -> ~[T] {
         let begin = slice.first();
         let end = slice.second();
 
         let v_len = end - begin;
         if v_len == 0 { return ~[]; }
-        if v_len == 1 { return ~[copy v[begin]]; }
+        if v_len == 1 { return ~[v[begin].clone()]; }
 
         let mid = v_len / 2 + begin;
         let a = (begin, mid);
@@ -45,7 +44,7 @@ pub fn merge_sort<T:Copy>(v: &[T], le: Le<T>) -> ~[T] {
                                     merge_sort_(v, b, |x,y| le(x,y)));
     }
 
-    fn merge<T:Copy>(le: Le<T>, a: &[T], b: &[T]) -> ~[T] {
+    fn merge<T:Copy + Clone>(le: Le<T>, a: &[T], b: &[T]) -> ~[T] {
         let mut rs = vec::with_capacity(a.len() + b.len());
         let a_len = a.len();
         let mut a_ix = 0;
@@ -53,9 +52,12 @@ pub fn merge_sort<T:Copy>(v: &[T], le: Le<T>) -> ~[T] {
         let mut b_ix = 0;
         while a_ix < a_len && b_ix < b_len {
             if le(&a[a_ix], &b[b_ix]) {
-                rs.push(copy a[a_ix]);
+                rs.push(a[a_ix].clone());
                 a_ix += 1;
-            } else { rs.push(copy b[b_ix]); b_ix += 1; }
+            } else {
+                rs.push(b[b_ix].clone());
+                b_ix += 1;
+            }
         }
         rs.push_all(a.slice(a_ix, a_len));
         rs.push_all(b.slice(b_ix, b_len));
@@ -104,9 +106,9 @@ pub fn quick_sort<T>(arr: &mut [T], compare_func: Le<T>) {
     qsort::<T>(arr, 0u, len - 1u, compare_func);
 }
 
-fn qsort3<T:Copy + Ord + Eq>(arr: &mut [T], left: int, right: int) {
+fn qsort3<T:Clone + Ord + Eq>(arr: &mut [T], left: int, right: int) {
     if right <= left { return; }
-    let v: T = copy arr[right];
+    let v: T = arr[right].clone();
     let mut i: int = left - 1;
     let mut j: int = right;
     let mut p: int = i;
@@ -161,7 +163,7 @@ fn qsort3<T:Copy + Ord + Eq>(arr: &mut [T], left: int, right: int) {
  *
  * This is an unstable sort.
  */
-pub fn quick_sort3<T:Copy + Ord + Eq>(arr: &mut [T]) {
+pub fn quick_sort3<T:Clone + Ord + Eq>(arr: &mut [T]) {
     if arr.len() <= 1 { return; }
     let len = arr.len(); // FIXME(#5074) nested calls
     qsort3(arr, 0, (len - 1) as int);
@@ -172,7 +174,7 @@ pub trait Sort {
     fn qsort(self);
 }
 
-impl<'self, T:Copy + Ord + Eq> Sort for &'self mut [T] {
+impl<'self, T:Clone + Ord + Eq> Sort for &'self mut [T] {
     fn qsort(self) { quick_sort3(self); }
 }
 
@@ -181,7 +183,7 @@ static MIN_GALLOP: uint = 7;
 static INITIAL_TMP_STORAGE: uint = 128;
 
 #[allow(missing_doc)]
-pub fn tim_sort<T:Copy + Ord>(array: &mut [T]) {
+pub fn tim_sort<T:Copy + Clone + Ord>(array: &mut [T]) {
     let size = array.len();
     if size < 2 {
         return;
@@ -225,7 +227,7 @@ pub fn tim_sort<T:Copy + Ord>(array: &mut [T]) {
     ms.merge_force_collapse(array);
 }
 
-fn binarysort<T:Copy + Ord>(array: &mut [T], start: uint) {
+fn binarysort<T:Copy + Clone + Ord>(array: &mut [T], start: uint) {
     let size = array.len();
     let mut start = start;
     assert!(start <= size);
@@ -233,7 +235,7 @@ fn binarysort<T:Copy + Ord>(array: &mut [T], start: uint) {
     if start == 0 { start += 1; }
 
     while start < size {
-        let pivot = copy array[start];
+        let pivot = array[start].clone();
         let mut left = 0;
         let mut right = start;
         assert!(left <= right);
@@ -275,7 +277,7 @@ fn min_run_length(n: uint) -> uint {
     return n + r;
 }
 
-fn count_run_ascending<T:Copy + Ord>(array: &mut [T]) -> uint {
+fn count_run_ascending<T:Clone + Ord>(array: &mut [T]) -> uint {
     let size = array.len();
     assert!(size > 0);
     if size == 1 { return 1; }
@@ -295,7 +297,7 @@ fn count_run_ascending<T:Copy + Ord>(array: &mut [T]) -> uint {
     return run;
 }
 
-fn gallop_left<T:Copy + Ord>(key: &T,
+fn gallop_left<T:Clone + Ord>(key: &T,
                              array: &[T],
                              hint: uint)
                           -> uint {
@@ -346,7 +348,7 @@ fn gallop_left<T:Copy + Ord>(key: &T,
     return ofs;
 }
 
-fn gallop_right<T:Copy + Ord>(key: &T,
+fn gallop_right<T:Clone + Ord>(key: &T,
                               array: &[T],
                               hint: uint)
                            -> uint {
@@ -417,7 +419,7 @@ fn MergeState<T>() -> MergeState<T> {
     }
 }
 
-impl<T:Copy + Ord> MergeState<T> {
+impl<T:Copy + Clone + Ord> MergeState<T> {
     fn push_run(&mut self, run_base: uint, run_len: uint) {
         let tmp = RunState{base: run_base, len: run_len};
         self.runs.push(tmp);
@@ -470,7 +472,7 @@ impl<T:Copy + Ord> MergeState<T> {
 
         let mut tmp = ~[];
         for uint::range(base1, base1+len1) |i| {
-            tmp.push(copy array[i]);
+            tmp.push(array[i].clone());
         }
 
         let mut c1 = 0;
@@ -580,7 +582,7 @@ impl<T:Copy + Ord> MergeState<T> {
 
         let mut tmp = ~[];
         for uint::range(base2, base2+len2) |i| {
-            tmp.push(copy array[i]);
+            tmp.push(array[i].clone());
         }
 
         let mut c1 = base1 + len1 - 1;
@@ -726,21 +728,21 @@ impl<T:Copy + Ord> MergeState<T> {
 }
 
 #[inline]
-fn copy_vec<T:Copy>(dest: &mut [T],
+fn copy_vec<T:Clone>(dest: &mut [T],
                     s1: uint,
                     from: &[T]) {
     assert!(s1+from.len() <= dest.len());
 
     for from.iter().enumerate().advance |(i, v)| {
-        dest[s1+i] = copy *v;
+        dest[s1+i] = (*v).clone();
     }
 }
 
 #[inline]
-fn shift_vec<T:Copy>(dest: &mut [T],
-                     s1: uint,
-                     s2: uint,
-                     len: uint) {
+fn shift_vec<T:Copy + Clone>(dest: &mut [T],
+                             s1: uint,
+                             s2: uint,
+                             len: uint) {
     assert!(s1+len <= dest.len());
 
     let tmp = dest.slice(s2, s2+len).to_owned();
@@ -902,7 +904,7 @@ mod tests {
         fn ile(x: &(&'static str), y: &(&'static str)) -> bool
         {
             // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-            // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+            // to_ascii_consume and to_str_consume to not do a unnecessary clone.
             // (Actually, could just remove the to_str_* call, but needs an deriving(Ord) on
             // Ascii)
             let x = x.to_ascii().to_lower().to_str_ascii();
@@ -1038,17 +1040,17 @@ mod big_tests {
         tabulate_managed(low, high);
     }
 
-    fn multiplyVec<T:Copy>(arr: &[T], num: uint) -> ~[T] {
+    fn multiplyVec<T:Clone>(arr: &[T], num: uint) -> ~[T] {
         let size = arr.len();
         let res = do vec::from_fn(num) |i| {
-            copy arr[i % size]
+            arr[i % size].clone()
         };
         res
     }
 
     fn makeRange(n: uint) -> ~[uint] {
         let one = do vec::from_fn(n) |i| { i };
-        let mut two = copy one;
+        let mut two = one.clone();
         two.reverse();
         vec::append(two, one)
     }
diff --git a/src/libextra/stats.rs b/src/libextra/stats.rs
index f488c03ce75..b891d022292 100644
--- a/src/libextra/stats.rs
+++ b/src/libextra/stats.rs
@@ -99,7 +99,7 @@ pub trait Stats {
 }
 
 /// Extracted collection of all the summary statistics of a sample set.
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 struct Summary {
     sum: f64,
     min: f64,
diff --git a/src/libextra/terminfo/parm.rs b/src/libextra/terminfo/parm.rs
index f25d192cc0a..840669f27b5 100644
--- a/src/libextra/terminfo/parm.rs
+++ b/src/libextra/terminfo/parm.rs
@@ -39,6 +39,7 @@ enum FormatState {
 }
 
 /// Types of parameters a capability can use
+#[deriving(Clone)]
 pub enum Param {
     String(~str),
     Number(int)
@@ -82,7 +83,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
     // Copy parameters into a local vector for mutability
     let mut mparams = [Number(0), ..9];
     for mparams.mut_iter().zip(params.iter()).advance |(dst, src)| {
-        *dst = copy *src;
+        *dst = (*src).clone();
     }
 
     for cap.iter().transform(|&x| x).advance |c| {
@@ -214,7 +215,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
                             _         => return Err(~"non-number on stack with %~")
                         }
                     } else { return Err(~"stack is empty") },
-                    'i' => match (copy mparams[0], copy mparams[1]) {
+                    'i' => match (mparams[0].clone(), mparams[1].clone()) {
                         (Number(x), Number(y)) => {
                             mparams[0] = Number(x+1);
                             mparams[1] = Number(y+1);
@@ -263,10 +264,10 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
             },
             PushParam => {
                 // params are 1-indexed
-                stack.push(copy mparams[match char::to_digit(cur, 10) {
+                stack.push(mparams[match char::to_digit(cur, 10) {
                     Some(d) => d - 1,
                     None => return Err(~"bad param number")
-                }]);
+                }].clone());
             },
             SetVar => {
                 if cur >= 'A' && cur <= 'Z' {
@@ -286,10 +287,10 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
             GetVar => {
                 if cur >= 'A' && cur <= 'Z' {
                     let idx = (cur as u8) - ('A' as u8);
-                    stack.push(copy vars.sta[idx]);
+                    stack.push(vars.sta[idx].clone());
                 } else if cur >= 'a' && cur <= 'z' {
                     let idx = (cur as u8) - ('a' as u8);
-                    stack.push(copy vars.dyn[idx]);
+                    stack.push(vars.dyn[idx].clone());
                 } else {
                     return Err(~"bad variable name in %g");
                 }
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index deef1fc3613..b45e1d6323b 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -44,13 +44,14 @@ use std::os;
 // colons. This way if some test runner wants to arrange the tests
 // hierarchically it may.
 
+#[deriving(Clone)]
 pub enum TestName {
     StaticTestName(&'static str),
     DynTestName(~str)
 }
 impl ToStr for TestName {
     fn to_str(&self) -> ~str {
-        match copy *self {
+        match (*self).clone() {
             StaticTestName(s) => s.to_str(),
             DynTestName(s) => s.to_str()
         }
@@ -80,6 +81,7 @@ pub struct BenchHarness {
 
 // The definition of a single test. A test runner will run a list of
 // these.
+#[deriving(Clone)]
 pub struct TestDesc {
     name: TestName,
     ignore: bool,
@@ -134,10 +136,10 @@ pub fn test_main_static(args: &[~str], tests: &[TestDescAndFn]) {
     let owned_tests = do tests.map |t| {
         match t.testfn {
             StaticTestFn(f) =>
-            TestDescAndFn { testfn: StaticTestFn(f), desc: copy t.desc },
+            TestDescAndFn { testfn: StaticTestFn(f), desc: t.desc.clone() },
 
             StaticBenchFn(f) =>
-            TestDescAndFn { testfn: StaticBenchFn(f), desc: copy t.desc },
+            TestDescAndFn { testfn: StaticBenchFn(f), desc: t.desc.clone() },
 
             _ => {
                 fail!("non-static tests passed to test::test_main_static");
@@ -178,8 +180,10 @@ pub fn parse_opts(args: &[~str]) -> OptRes {
 
     let filter =
         if matches.free.len() > 0 {
-            Some(copy (matches).free[0])
-        } else { None };
+            Some((matches).free[0].clone())
+        } else {
+            None
+        };
 
     let run_ignored = getopts::opt_present(&matches, "ignored");
 
@@ -214,19 +218,19 @@ pub fn parse_opts(args: &[~str]) -> OptRes {
     either::Left(test_opts)
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct BenchSamples {
     ns_iter_summ: stats::Summary,
     mb_s: uint
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum TestResult {
     TrOk,
     TrFailed,
     TrIgnored,
     TrMetrics(MetricMap),
-    TrBench(BenchSamples)
+    TrBench(BenchSamples),
 }
 
 struct ConsoleTestState {
@@ -500,7 +504,7 @@ pub fn run_tests_console(opts: &TestOpts,
                          tests: ~[TestDescAndFn]) -> bool {
     fn callback(event: &TestEvent, st: &mut ConsoleTestState) {
         debug!("callback(event=%?)", event);
-        match copy *event {
+        match (*event).clone() {
             TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
             TeWait(ref test) => st.write_test_start(test),
             TeResult(test, result) => {
@@ -584,6 +588,7 @@ fn should_sort_failures_before_printing_them() {
 
 fn use_color() -> bool { return get_concurrency() == 1; }
 
+#[deriving(Clone)]
 enum TestEvent {
     TeFiltered(~[TestDesc]),
     TeWait(TestDesc),
@@ -597,7 +602,7 @@ fn run_tests(opts: &TestOpts,
              callback: &fn(e: TestEvent)) {
 
     let filtered_tests = filter_tests(opts, tests);
-    let filtered_descs = filtered_tests.map(|t| copy t.desc);
+    let filtered_descs = filtered_tests.map(|t| t.desc.clone());
 
     callback(TeFiltered(filtered_descs));
 
@@ -628,7 +633,7 @@ fn run_tests(opts: &TestOpts,
                 // We are doing one test at a time so we can print the name
                 // of the test before we run it. Useful for debugging tests
                 // that hang forever.
-                callback(TeWait(copy test.desc));
+                callback(TeWait(test.desc.clone()));
             }
             run_test(!opts.run_tests, test, ch.clone());
             pending += 1;
@@ -636,7 +641,7 @@ fn run_tests(opts: &TestOpts,
 
         let (desc, result) = p.recv();
         if concurrency != 1 {
-            callback(TeWait(copy desc));
+            callback(TeWait(desc.clone()));
         }
         callback(TeResult(desc, result));
         pending -= 1;
@@ -645,7 +650,7 @@ fn run_tests(opts: &TestOpts,
     // All benchmarks run at the end, in serial.
     // (this includes metric fns)
     for filtered_benchs_and_metrics.consume_iter().advance |b| {
-        callback(TeWait(copy b.desc));
+        callback(TeWait(b.desc.clone()));
         run_test(!opts.run_benchmarks, b, ch.clone());
         let (test, result) = p.recv();
         callback(TeResult(test, result));
@@ -678,7 +683,7 @@ pub fn filter_tests(
         filtered
     } else {
         let filter_str = match opts.filter {
-          Some(ref f) => copy *f,
+          Some(ref f) => (*f).clone(),
           None => ~""
         };
 
@@ -752,7 +757,7 @@ pub fn run_test(force_ignore: bool,
             let task_result = result_future.unwrap().recv();
             let test_result = calc_result(&desc,
                                           task_result == task::Success);
-            monitor_ch.send((copy desc, test_result));
+            monitor_ch.send((desc.clone(), test_result));
         }
     }
 
@@ -813,14 +818,14 @@ impl MetricMap {
     /// Load MetricDiff from a file.
     pub fn load(p: &Path) -> MetricMap {
         assert!(os::path_exists(p));
-        let f = io::file_reader(p).get();
+        let f = io::file_reader(p).unwrap();
         let mut decoder = json::Decoder(json::from_reader(f).get());
         MetricMap(Decodable::decode(&mut decoder))
     }
 
     /// Write MetricDiff to a file.
     pub fn save(&self, p: &Path) {
-        let f = io::file_writer(p, [io::Create, io::Truncate]).get();
+        let f = io::file_writer(p, [io::Create, io::Truncate]).unwrap();
         json::to_pretty_writer(f, &self.to_json());
     }
 
@@ -868,11 +873,11 @@ impl MetricMap {
                     }
                 }
             };
-            diff.insert(copy *k, r);
+            diff.insert((*k).clone(), r);
         }
         for self.iter().advance |(k, _)| {
             if !diff.contains_key(k) {
-                diff.insert(copy *k, MetricAdded);
+                diff.insert((*k).clone(), MetricAdded);
             }
         }
         diff
@@ -1153,7 +1158,7 @@ mod tests {
           either::Left(o) => o,
           _ => fail!("Malformed arg in first_free_arg_should_be_a_filter")
         };
-        assert!("filter" == (copy opts.filter).get());
+        assert!("filter" == opts.filter.clone().get());
     }
 
     #[test]
@@ -1236,11 +1241,11 @@ mod tests {
             for names.iter().advance |name| {
                 let test = TestDescAndFn {
                     desc: TestDesc {
-                        name: DynTestName(copy *name),
+                        name: DynTestName((*name).clone()),
                         ignore: false,
                         should_fail: false
                     },
-                    testfn: DynTestFn(copy testfn),
+                    testfn: DynTestFn(testfn.clone()),
                 };
                 tests.push(test);
             }
diff --git a/src/libextra/time.rs b/src/libextra/time.rs
index d74656dcc2e..a3b85b05d5d 100644
--- a/src/libextra/time.rs
+++ b/src/libextra/time.rs
@@ -683,7 +683,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> {
                 tm_yday: tm.tm_yday,
                 tm_isdst: tm.tm_isdst,
                 tm_gmtoff: tm.tm_gmtoff,
-                tm_zone: copy tm.tm_zone,
+                tm_zone: tm.tm_zone.clone(),
                 tm_nsec: tm.tm_nsec,
             })
         } else { result }
@@ -829,7 +829,7 @@ priv fn do_strftime(format: &str, tm: &Tm) -> ~str {
           //'x' {}
           'Y' => int::to_str(tm.tm_year as int + 1900),
           'y' => fmt!("%02d", (tm.tm_year as int + 1900) % 100),
-          'Z' => copy tm.tm_zone,
+          'Z' => tm.tm_zone.clone(),
           'z' => {
             let sign = if tm.tm_gmtoff > 0_i32 { '+' } else { '-' };
             let mut m = num::abs(tm.tm_gmtoff) / 60_i32;
diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs
index bd13c8619be..223e17d0952 100644
--- a/src/libextra/treemap.rs
+++ b/src/libextra/treemap.rs
@@ -791,8 +791,8 @@ mod test_treemap {
         let v1 = "baz".as_bytes();
         let v2 = "foobar".as_bytes();
 
-        m.insert(copy k1, copy v1);
-        m.insert(copy k2, copy v2);
+        m.insert(k1.clone(), v1.clone());
+        m.insert(k2.clone(), v2.clone());
 
         assert_eq!(m.find(&k2), Some(&v2));
         assert_eq!(m.find(&k1), Some(&v1));
diff --git a/src/libextra/uv_ll.rs b/src/libextra/uv_ll.rs
index 69ff1007840..74798d260c1 100644
--- a/src/libextra/uv_ll.rs
+++ b/src/libextra/uv_ll.rs
@@ -1476,7 +1476,7 @@ mod test {
                 let client_data = get_data_for_uv_handle(
                     client_stream_ptr as *libc::c_void) as *tcp_server_data;
 
-                let server_kill_msg = copy (*client_data).server_kill_msg;
+                let server_kill_msg = (*client_data).server_kill_msg.clone();
                 let write_req = (*client_data).server_write_req;
                 if request_str.contains(server_kill_msg) {
                     debug!(~"SERVER: client req contains kill_msg!");
@@ -1726,12 +1726,12 @@ mod test {
         let (continue_port, continue_chan) = stream::<bool>();
         let continue_chan = SharedChan::new(continue_chan);
 
-        let kill_server_msg_copy = copy kill_server_msg;
-        let server_resp_msg_copy = copy server_resp_msg;
+        let kill_server_msg_copy = kill_server_msg.clone();
+        let server_resp_msg_copy = server_resp_msg.clone();
         do task::spawn_sched(task::ManualThreads(1)) {
             impl_uv_tcp_server(bind_ip, port,
-                               copy kill_server_msg_copy,
-                               copy server_resp_msg_copy,
+                               kill_server_msg_copy.clone(),
+                               server_resp_msg_copy.clone(),
                                server_chan.clone(),
                                continue_chan.clone());
         };
@@ -1741,7 +1741,7 @@ mod test {
         continue_port.recv();
         debug!(~"received on continue port, set up tcp client");
 
-        let kill_server_msg_copy = copy kill_server_msg;
+        let kill_server_msg_copy = kill_server_msg.clone();
         do task::spawn_sched(task::ManualThreads(1u)) {
             impl_uv_tcp_request(request_ip, port,
                                kill_server_msg_copy,
diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs
index e7bec2fbd8d..99cf8c6912c 100644
--- a/src/libextra/workcache.rs
+++ b/src/libextra/workcache.rs
@@ -97,7 +97,7 @@ use std::util::replace;
 *
 */
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Clone, Eq, Encodable, Decodable)]
 struct WorkKey {
     kind: ~str,
     name: ~str
@@ -138,6 +138,12 @@ impl WorkKey {
 
 struct WorkMap(HashMap<WorkKey, ~str>);
 
+impl Clone for WorkMap {
+    fn clone(&self) -> WorkMap {
+        WorkMap((**self).clone())
+    }
+}
+
 impl WorkMap {
     fn new() -> WorkMap { WorkMap(HashMap::new()) }
 }
@@ -146,7 +152,7 @@ impl<S:Encoder> Encodable<S> for WorkMap {
     fn encode(&self, s: &mut S) {
         let mut d = ~[];
         for self.iter().advance |(k, v)| {
-            d.push((copy *k, copy *v))
+            d.push(((*k).clone(), (*v).clone()))
         }
         sort::tim_sort(d);
         d.encode(s)
@@ -215,6 +221,7 @@ struct Context {
     freshness: HashMap<~str,@fn(&str,&str)->bool>
 }
 
+#[deriving(Clone)]
 struct Prep {
     ctxt: @Context,
     fn_name: ~str,
@@ -341,7 +348,7 @@ impl TPrep for Prep {
                               &self.declared_inputs) &&
             self.all_fresh("discovered input", disc_in) &&
             self.all_fresh("discovered output", disc_out) => {
-                Work::new(@mut copy *self, Left(json_decode(*res)))
+                Work::new(@mut (*self).clone(), Left(json_decode(*res)))
             }
 
             _ => {
@@ -358,7 +365,7 @@ impl TPrep for Prep {
                     let v = blk(&exe);
                     send_one(chan, (exe, v));
                 }
-                Work::new(@mut copy *self, Right(port))
+                Work::new(@mut (*self).clone(), Right(port))
             }
         }
     }
@@ -413,7 +420,7 @@ fn test() {
     let w:Work<~str> = do cx.prep("test1") |prep| {
         let pth = Path("foo.c");
         {
-            let file = io::file_writer(&pth, [io::Create]).get();
+            let file = io::file_writer(&pth, [io::Create]).unwrap();
             file.write_str("int main() { return 0; }");
         }
 
diff --git a/src/librust/rust.rs b/src/librust/rust.rs
index 670ece11dbd..adf73a7e7f0 100644
--- a/src/librust/rust.rs
+++ b/src/librust/rust.rs
@@ -118,7 +118,7 @@ static COMMANDS: &'static [Command<'static>] = &[
 ];
 
 fn rustc_help() {
-    rustc::usage(copy os::args()[0])
+    rustc::usage(os::args()[0].clone())
 }
 
 fn find_cmd(command_string: &str) -> Option<Command> {
@@ -148,7 +148,7 @@ fn cmd_help(args: &[~str]) -> ValidUsage {
     }
 
     match args {
-        [ref command_string] => print_usage(copy *command_string),
+        [ref command_string] => print_usage((*command_string).clone()),
         _                    => Invalid
     }
 }
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index aeed2d842c1..98fd37d7633 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -39,7 +39,7 @@ use syntax::attr;
 use syntax::print::pprust;
 use syntax::parse::token;
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum output_type {
     output_type_none,
     output_type_bitcode,
@@ -291,7 +291,7 @@ pub mod write {
             }
 
             let passes = if sess.opts.custom_passes.len() > 0 {
-                copy sess.opts.custom_passes
+                sess.opts.custom_passes.clone()
             } else {
                 if sess.lint_llvm() {
                     mpm.add_pass_from_name("lint");
@@ -817,7 +817,7 @@ pub fn link_binary(sess: Session,
     // For win32, there is no cc command,
     // so we add a condition to make it use gcc.
     let cc_prog: ~str = match sess.opts.linker {
-        Some(ref linker) => copy *linker,
+        Some(ref linker) => linker.to_str(),
         None => match sess.targ_cfg.os {
             session::os_android =>
                 match &sess.opts.android_cross_path {
@@ -845,7 +845,7 @@ pub fn link_binary(sess: Session,
 
         out_filename.dir_path().push(long_libname)
     } else {
-        /*bad*/copy *out_filename
+        out_filename.clone()
     };
 
     debug!("output: %s", output.to_str());
@@ -896,7 +896,7 @@ pub fn link_args(sess: Session,
         let long_libname = output_dll_filename(sess.targ_cfg.os, lm);
         out_filename.dir_path().push(long_libname)
     } else {
-        /*bad*/copy *out_filename
+        out_filename.clone()
     };
 
     // The default library location, we need this to find the runtime.
diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index 62c1f670cf9..c56ed34309c 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -185,7 +185,7 @@ pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
     let mut minimized = ~[];
     for rpaths.iter().advance |rpath| {
         if set.insert(rpath.to_str()) {
-            minimized.push(copy *rpath);
+            minimized.push(rpath.clone());
         }
     }
     minimized
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 15ce8c4c7e2..2c1f3dd1918 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -109,10 +109,14 @@ pub fn build_configuration(sess: Session, argv0: @str, input: &input) ->
     // Combine the configuration requested by the session (command line) with
     // some default and generated configuration items
     let default_cfg = default_configuration(sess, argv0, input);
-    let user_cfg = /*bad*/copy sess.opts.cfg;
+    let user_cfg = sess.opts.cfg.clone();
     // If the user wants a test runner, then add the test cfg
-    let user_cfg = if sess.opts.test { append_configuration(user_cfg, @"test") }
-                   else { user_cfg };
+    let user_cfg = if sess.opts.test {
+        append_configuration(user_cfg, @"test")
+    } else {
+        user_cfg
+    };
+
     // If the user requested GC, then add the GC cfg
     let user_cfg = append_configuration(
         user_cfg,
@@ -202,7 +206,8 @@ pub fn compile_rest(sess: Session,
                      front::config::strip_unconfigured_items(crate));
 
         crate = time(time_passes, ~"expansion", ||
-                     syntax::ext::expand::expand_crate(sess.parse_sess, copy cfg,
+                     syntax::ext::expand::expand_crate(sess.parse_sess,
+                                                       cfg.clone(),
                                                        crate));
 
         // strip again, in case expansion added anything with a #[cfg].
@@ -213,7 +218,9 @@ pub fn compile_rest(sess: Session,
                      front::test::modify_for_testing(sess, crate));
     }
 
-    if phases.to == cu_expand { return (Some(crate), None); }
+    if phases.to == cu_expand {
+        return (Some(crate), None);
+    }
 
     assert!(phases.from != cu_no_trans);
 
@@ -371,17 +378,28 @@ pub fn compile_rest(sess: Session,
     return (None, None);
 }
 
-pub fn compile_upto(sess: Session, cfg: ast::crate_cfg,
-                input: &input, upto: compile_phase,
-                outputs: Option<@OutputFilenames>)
-    -> (Option<@ast::crate>, Option<ty::ctxt>) {
+pub fn compile_upto(sess: Session,
+                    cfg: ast::crate_cfg,
+                    input: &input,
+                    upto: compile_phase,
+                    outputs: Option<@OutputFilenames>)
+                    -> (Option<@ast::crate>, Option<ty::ctxt>) {
     let time_passes = sess.time_passes();
-    let crate = time(time_passes, ~"parsing",
-                         || parse_input(sess, copy cfg, input) );
-    if upto == cu_parse { return (Some(crate), None); }
+    let crate = time(time_passes,
+                     ~"parsing",
+                     || parse_input(sess, cfg.clone(), input) );
+    if upto == cu_parse {
+        return (Some(crate), None);
+    }
 
-    compile_rest(sess, cfg, compile_upto { from: cu_parse, to: upto },
-                 outputs, Some(crate))
+    compile_rest(sess,
+                 cfg,
+                 compile_upto {
+                    from: cu_parse,
+                    to: upto
+                 },
+                 outputs,
+                 Some(crate))
 }
 
 pub fn compile_input(sess: Session, cfg: ast::crate_cfg, input: &input,
@@ -877,7 +895,7 @@ pub fn build_output_filenames(input: &input,
           // have to make up a name
           // We want to toss everything after the final '.'
           let dirpath = match *odir {
-              Some(ref d) => (/*bad*/copy *d),
+              Some(ref d) => (*d).clone(),
               None => match *input {
                   str_input(_) => os::getcwd(),
                   file_input(ref ifile) => (*ifile).dir_path()
@@ -914,9 +932,9 @@ pub fn build_output_filenames(input: &input,
       }
 
       Some(ref out_file) => {
-        out_path = (/*bad*/copy *out_file);
+        out_path = (*out_file).clone();
         obj_path = if stop_after_codegen {
-            (/*bad*/copy *out_file)
+            (*out_file).clone()
         } else {
             (*out_file).with_filetype(obj_suffix)
         };
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index ef0b6d64651..7579616b4ce 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -33,7 +33,12 @@ use std::hashmap::HashMap;
 #[deriving(Eq)]
 pub enum os { os_win32, os_macos, os_linux, os_android, os_freebsd, }
 
-pub enum crate_type { bin_crate, lib_crate, unknown_crate, }
+#[deriving(Clone)]
+pub enum crate_type {
+    bin_crate,
+    lib_crate,
+    unknown_crate,
+}
 
 pub struct config {
     os: os,
@@ -118,7 +123,7 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
     ]
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum OptLevel {
     No, // -O0
     Less, // -O1
@@ -126,6 +131,7 @@ pub enum OptLevel {
     Aggressive // -O3
 }
 
+#[deriving(Clone)]
 pub struct options {
     // The crate config requested for the session, which may be combined
     // with additional crate configurations during the compile process
@@ -345,10 +351,8 @@ pub fn basic_options() -> @options {
 }
 
 // Seems out of place, but it uses session, so I'm putting it here
-pub fn expect<T:Copy>(sess: Session,
-                       opt: Option<T>,
-                       msg: &fn() -> ~str)
-                    -> T {
+pub fn expect<T:Clone>(sess: Session, opt: Option<T>, msg: &fn() -> ~str)
+                       -> T {
     diagnostic::expect(sess.diagnostic(), opt, msg)
 }
 
diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs
index 0768d674671..88524781191 100644
--- a/src/librustc/front/config.rs
+++ b/src/librustc/front/config.rs
@@ -99,14 +99,14 @@ fn fold_item_underscore(cx: @Context, item: &ast::item_,
         ast::item_impl(ref a, ref b, ref c, ref methods) => {
             let methods = methods.iter().filter(|m| method_in_cfg(cx, **m))
                 .transform(|x| *x).collect();
-            ast::item_impl(/*bad*/ copy *a, /*bad*/ copy *b, /*bad*/ copy *c, methods)
+            ast::item_impl((*a).clone(), (*b).clone(), (*c).clone(), methods)
         }
         ast::item_trait(ref a, ref b, ref methods) => {
             let methods = methods.iter().filter(|m| trait_method_in_cfg(cx, *m) )
-                .transform(|x| /* bad */copy *x).collect();
-            ast::item_trait(/*bad*/copy *a, /*bad*/copy *b, methods)
+                .transform(|x| (*x).clone()).collect();
+            ast::item_trait((*a).clone(), (*b).clone(), methods)
         }
-        ref item => /*bad*/ copy *item
+        ref item => (*item).clone(),
     };
 
     fold::noop_fold_item_underscore(&item, fld)
@@ -151,11 +151,11 @@ fn fold_block(
 }
 
 fn item_in_cfg(cx: @Context, item: @ast::item) -> bool {
-    return (cx.in_cfg)(/*bad*/copy item.attrs);
+    return (cx.in_cfg)(item.attrs);
 }
 
 fn foreign_item_in_cfg(cx: @Context, item: @ast::foreign_item) -> bool {
-    return (cx.in_cfg)(/*bad*/copy item.attrs);
+    return (cx.in_cfg)(item.attrs);
 }
 
 fn view_item_in_cfg(cx: @Context, item: &ast::view_item) -> bool {
@@ -163,13 +163,13 @@ fn view_item_in_cfg(cx: @Context, item: &ast::view_item) -> bool {
 }
 
 fn method_in_cfg(cx: @Context, meth: @ast::method) -> bool {
-    return (cx.in_cfg)(/*bad*/copy meth.attrs);
+    return (cx.in_cfg)(meth.attrs);
 }
 
 fn trait_method_in_cfg(cx: @Context, meth: &ast::trait_method) -> bool {
     match *meth {
-        ast::required(ref meth) => (cx.in_cfg)(/*bad*/copy meth.attrs),
-        ast::provided(@ref meth) => (cx.in_cfg)(/*bad*/copy meth.attrs)
+        ast::required(ref meth) => (cx.in_cfg)(meth.attrs),
+        ast::provided(@ref meth) => (cx.in_cfg)(meth.attrs)
     }
 }
 
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index ee0ce32bfec..3d4b22ecd8c 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -64,7 +64,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
             let vis = vec::append(~[vi1], crate.module.view_items);
             let mut new_module = ast::_mod {
                 view_items: vis,
-                ../*bad*/copy crate.module
+                ..crate.module.clone()
             };
 
             if !no_prelude(crate.attrs) {
@@ -76,7 +76,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
             // FIXME #2543: Bad copy.
             let new_crate = ast::crate_ {
                 module: new_module,
-                ..copy *crate
+                ..(*crate).clone()
             };
             (new_crate, span)
         },
@@ -115,7 +115,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
             // FIXME #2543: Bad copy.
             let new_module = ast::_mod {
                 view_items: vis,
-                ..copy *module
+                ..(*module).clone()
             };
             fold::noop_fold_mod(&new_module, fld)
         },
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index 7137272acda..61a530b307c 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -66,7 +66,7 @@ fn generate_test_harness(sess: session::Session,
     let cx: @mut TestCtxt = @mut TestCtxt {
         sess: sess,
         crate: crate,
-        ext_cx: ExtCtxt::new(sess.parse_sess, copy sess.opts.cfg),
+        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
         path: ~[],
         testfns: ~[]
     };
@@ -109,26 +109,31 @@ fn fold_mod(cx: @mut TestCtxt,
 
     fn nomain(cx: @mut TestCtxt, item: @ast::item) -> @ast::item {
         if !*cx.sess.building_library {
-            @ast::item{
+            @ast::item {
                 attrs: do item.attrs.iter().filter_map |attr| {
-                    if "main" != attr::get_attr_name(attr) {Some(*attr)} else {None}
+                    if "main" != attr::get_attr_name(attr) {
+                        Some(*attr)
+                    } else {
+                        None
+                    }
                 }.collect(),
-                .. copy *item}
-        } else { item }
+                .. (*item).clone()
+            }
+        } else {
+            item
+        }
     }
 
     let mod_nomain = ast::_mod {
-        view_items: /*bad*/copy m.view_items,
+        view_items: m.view_items.clone(),
         items: m.items.iter().transform(|i| nomain(cx, *i)).collect(),
     };
 
     fold::noop_fold_mod(&mod_nomain, fld)
 }
 
-fn fold_crate(cx: @mut TestCtxt,
-              c: &ast::crate_,
-              fld: @fold::ast_fold)
-           -> ast::crate_ {
+fn fold_crate(cx: @mut TestCtxt, c: &ast::crate_, fld: @fold::ast_fold)
+              -> ast::crate_ {
     let folded = fold::noop_fold_crate(c, fld);
 
     // Add a special __test module to the crate that will contain code
@@ -144,7 +149,7 @@ fn fold_item(cx: @mut TestCtxt, i: @ast::item, fld: @fold::ast_fold)
           -> Option<@ast::item> {
     cx.path.push(i.ident);
     debug!("current path: %s",
-           ast_util::path_name_i(copy cx.path));
+           ast_util::path_name_i(cx.path.clone()));
 
     if is_test_fn(cx, i) || is_bench_fn(i) {
         match i.node {
@@ -158,7 +163,7 @@ fn fold_item(cx: @mut TestCtxt, i: @ast::item, fld: @fold::ast_fold)
             debug!("this is a test function");
             let test = Test {
                 span: i.span,
-                path: /*bad*/copy cx.path,
+                path: cx.path.clone(),
                 bench: is_bench_fn(i),
                 ignore: is_ignored(cx, i),
                 should_fail: should_fail(i)
@@ -235,7 +240,7 @@ fn is_ignored(cx: @mut TestCtxt, i: @ast::item) -> bool {
             .filter_map(|i| attr::get_meta_item_list(i))
             .collect::<~[~[@ast::meta_item]]>()
             .concat_vec();
-        config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas)
+        config::metas_in_cfg(cx.crate.node.config.clone(), cfg_metas)
     } else {
         false
     }
@@ -248,8 +253,8 @@ fn should_fail(i: @ast::item) -> bool {
 fn add_test_module(cx: &TestCtxt, m: &ast::_mod) -> ast::_mod {
     let testmod = mk_test_module(cx);
     ast::_mod {
-        items: vec::append_one(/*bad*/copy m.items, testmod),
-        .. /*bad*/ copy *m
+        items: vec::append_one(m.items.clone(), testmod),
+        ..(*m).clone()
     }
 }
 
@@ -333,7 +338,7 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::item {
      };
 
     debug!("Synthetic test module:\n%s\n",
-           pprust::item_to_str(@copy item, cx.sess.intr()));
+           pprust::item_to_str(@item.clone(), cx.sess.intr()));
 
     return @item;
 }
@@ -406,7 +411,7 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::expr {
 
 fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr {
     let span = test.span;
-    let path = /*bad*/copy test.path;
+    let path = test.path.clone();
 
     let ext_cx = cx.ext_cx;
 
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 8ca8c12f412..aeb2017c9d6 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -58,6 +58,7 @@ pub enum Linkage {
     LinkerPrivateWeakLinkage = 16,
 }
 
+#[deriving(Clone)]
 pub enum Attribute {
     ZExtAttribute = 1,
     SExtAttribute = 2,
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 8c62f4dbbe3..dea263532b2 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -82,8 +82,7 @@ fn warn_if_multiple_versions(e: @mut Env,
         );
 
         let vec: ~[Either<cache_entry, cache_entry>] = crate_cache.iter().transform(|&entry| {
-            let othername = loader::crate_name_from_metas(
-                copy *entry.metas);
+            let othername = loader::crate_name_from_metas(*entry.metas);
             if name == othername {
                 Left(entry)
             } else {
@@ -100,8 +99,8 @@ fn warn_if_multiple_versions(e: @mut Env,
             for matches.iter().advance |match_| {
                 diag.span_note(match_.span, "used here");
                 let attrs = ~[
-                    attr::mk_attr(attr::mk_list_item(
-                        @"link", /*bad*/copy *match_.metas))
+                    attr::mk_attr(attr::mk_list_item(@"link",
+                                                     (*match_.metas).clone()))
                 ];
                 loader::note_linkage_attrs(e.intr, diag, attrs);
             }
@@ -141,7 +140,11 @@ fn visit_view_item(e: @mut Env, i: &ast::view_item) {
       ast::view_item_extern_mod(ident, ref meta_items, id) => {
         debug!("resolving extern mod stmt. ident: %?, meta: %?",
                ident, *meta_items);
-        let cnum = resolve_crate(e, ident, copy *meta_items, @"", i.span);
+        let cnum = resolve_crate(e,
+                                 ident,
+                                 (*meta_items).clone(),
+                                 @"",
+                                 i.span);
         cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum);
       }
       _ => ()
@@ -306,8 +309,8 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
         let cmetas = metas_with(dep.vers, @"vers", ~[]);
         debug!("resolving dep crate %s ver: %s hash: %s",
                cname_str, dep.vers, dep.hash);
-        match existing_match(e, metas_with_ident(cname_str,
-                                                 copy cmetas),
+        match existing_match(e,
+                             metas_with_ident(cname_str, cmetas.clone()),
                              dep.hash) {
           Some(local_cnum) => {
             debug!("already have it");
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index bb1834dc5c8..7f4bfea568f 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -91,12 +91,13 @@ pub fn iter_crate_data(cstore: &CStore,
 
 pub fn add_used_crate_file(cstore: &mut CStore, lib: &Path) {
     if !cstore.used_crate_files.contains(lib) {
-        cstore.used_crate_files.push(copy *lib);
+        cstore.used_crate_files.push((*lib).clone());
     }
 }
 
 pub fn get_used_crate_files(cstore: &CStore) -> ~[Path] {
-    return /*bad*/copy cstore.used_crate_files;
+    // XXX(pcwalton): Bad copy.
+    return cstore.used_crate_files.clone();
 }
 
 pub fn add_used_library(cstore: &mut CStore, lib: @str) -> bool {
@@ -135,10 +136,16 @@ pub fn find_extern_mod_stmt_cnum(cstore: &CStore,
     cstore.extern_mod_crate_map.find(&emod_id).map_consume(|x| *x)
 }
 
+#[deriving(Clone)]
+struct crate_hash {
+    name: @str,
+    vers: @str,
+    hash: @str,
+}
+
 // returns hashes of crates directly used by this crate. Hashes are sorted by
 // (crate name, crate version, crate hash) in lexicographic order (not semver)
 pub fn get_dep_hashes(cstore: &CStore) -> ~[@str] {
-    struct crate_hash { name: @str, vers: @str, hash: @str }
     let mut result = ~[];
 
     for cstore.extern_mod_crate_map.each_value |&cnum| {
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 2eafc1965b2..caa170605de 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -714,7 +714,7 @@ pub fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt,
         let item_path = item_path(item_doc);
         item_path.init().to_owned()
     };
-    match decode_inlined_item(cdata, tcx, copy path, item_doc) {
+    match decode_inlined_item(cdata, tcx, /*bad*/path.clone(), item_doc) {
       Some(ref ii) => csearch::found(*ii),
       None => {
         match item_parent_item(item_doc) {
@@ -746,7 +746,7 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
                                 item, tcx, cdata);
         let name = item_name(intr, item);
         let arg_tys = match ty::get(ctor_ty).sty {
-          ty::ty_bare_fn(ref f) => copy f.sig.inputs,
+          ty::ty_bare_fn(ref f) => f.sig.inputs.clone(),
           _ => ~[], // Nullary enum variant.
         };
         match variant_disr_val(item) {
@@ -1149,6 +1149,7 @@ pub fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] {
     return get_attributes(reader::Doc(data));
 }
 
+#[deriving(Clone)]
 pub struct crate_dep {
     cnum: ast::crate_num,
     name: ast::ident,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 1dead50b01a..ab42e84e2ac 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -128,6 +128,7 @@ fn encode_region_param(ecx: &EncodeContext,
     }
 }
 
+#[deriving(Clone)]
 struct entry<T> {
     val: T,
     pos: uint
@@ -662,7 +663,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
                           -> ~[entry<int>] {
     /* Each class has its own index, since different classes
        may have fields with the same name */
-    let index = @mut ~[];
+    let mut index = ~[];
     let tcx = ecx.tcx;
      /* We encode both private and public fields -- need to include
         private fields to get the offsets right */
@@ -685,7 +686,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
         encode_def_id(ebml_w, local_def(id));
         ebml_w.end_tag();
     }
-    /*bad*/copy *index
+    index
 }
 
 // This is for encoding info for ctors and dtors
@@ -781,10 +782,10 @@ fn encode_info_for_method(ecx: &EncodeContext,
 
     let mut combined_ty_params = opt_vec::Empty;
     for owner_generics.ty_params.iter().advance |x| {
-        combined_ty_params.push(copy *x)
+        combined_ty_params.push((*x).clone())
     }
     for method_generics.ty_params.iter().advance |x| {
-        combined_ty_params.push(copy *x)
+        combined_ty_params.push((*x).clone())
     }
     let len = combined_ty_params.len();
     encode_type_param_bounds(ebml_w, ecx, &combined_ty_params);
@@ -1151,7 +1152,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
                                 ebml_w: &mut writer::Encoder,
                                 nitem: @foreign_item,
                                 index: @mut ~[entry<int>],
-                                path: ast_map::path,
+                                path: &ast_map::path,
                                 abi: AbiSet) {
     index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() });
 
@@ -1164,11 +1165,11 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
         encode_name(ecx, ebml_w, nitem.ident);
         if abi.is_intrinsic() {
-            (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_foreign(nitem));
+            (ecx.encode_inlined_item)(ecx, ebml_w, *path, ii_foreign(nitem));
         } else {
             encode_symbol(ecx, ebml_w, nitem.id);
         }
-        encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
+        encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
       }
       foreign_item_static(_, mutbl) => {
         encode_def_id(ebml_w, local_def(nitem.id));
@@ -1180,7 +1181,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
         encode_symbol(ecx, ebml_w, nitem.id);
         encode_name(ecx, ebml_w, nitem.ident);
-        encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
+        encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
       }
     }
     ebml_w.end_tag();
@@ -1208,12 +1209,12 @@ fn encode_info_for_items(ecx: &EncodeContext,
     visit::visit_crate(crate, ((), visit::mk_vt(@visit::Visitor {
         visit_expr: |_e, (_cx, _v)| { },
         visit_item: {
-            let ebml_w = copy *ebml_w;
+            let ebml_w = (*ebml_w).clone();
             |i, (cx, v)| {
                 visit::visit_item(i, (cx, v));
                 match items.get_copy(&i.id) {
                     ast_map::node_item(_, pt) => {
-                        let mut ebml_w = copy ebml_w;
+                        let mut ebml_w = ebml_w.clone();
                         // See above
                         let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
                         encode_info_for_item(ecx, &mut ebml_w, i, index, *pt);
@@ -1223,7 +1224,7 @@ fn encode_info_for_items(ecx: &EncodeContext,
             }
         },
         visit_foreign_item: {
-            let ebml_w = copy *ebml_w;
+            let ebml_w = (*ebml_w).clone();
             |ni, (cx, v)| {
                 visit::visit_foreign_item(ni, (cx, v));
                 match items.get_copy(&ni.id) {
@@ -1234,14 +1235,14 @@ fn encode_info_for_items(ecx: &EncodeContext,
                                 token::get_ident_interner()),
                                 token::ident_to_str(&ni.ident));
 
-                        let mut ebml_w = copy ebml_w;
+                        let mut ebml_w = ebml_w.clone();
                         // See above
                         let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
                         encode_info_for_foreign_item(ecx,
                                                      &mut ebml_w,
                                                      ni,
                                                      index,
-                                                     /*bad*/copy *pt,
+                                                     pt,
                                                      abi);
                     }
                     // case for separate item and foreign-item tables
@@ -1252,24 +1253,24 @@ fn encode_info_for_items(ecx: &EncodeContext,
         ..*visit::default_visitor()
     })));
     ebml_w.end_tag();
-    return /*bad*/copy *index;
+    return /*bad*/(*index).clone();
 }
 
 
 // Path and definition ID indexing
 
-fn create_index<T:Copy + Hash + IterBytes>(index: ~[entry<T>]) ->
-   ~[@~[entry<T>]] {
+fn create_index<T:Clone + Hash + IterBytes>(index: ~[entry<T>])
+                                            -> ~[@~[entry<T>]] {
     let mut buckets: ~[@mut ~[entry<T>]] = ~[];
     for uint::range(0u, 256u) |_i| { buckets.push(@mut ~[]); };
     for index.iter().advance |elt| {
         let h = elt.val.hash() as uint;
-        buckets[h % 256].push(copy *elt);
+        buckets[h % 256].push((*elt).clone());
     }
 
     let mut buckets_frozen = ~[];
     for buckets.iter().advance |bucket| {
-        buckets_frozen.push(@/*bad*/copy **bucket);
+        buckets_frozen.push(@/*bad*/(**bucket).clone());
     }
     return buckets_frozen;
 }
@@ -1401,7 +1402,7 @@ fn synthesize_crate_attrs(ecx: &EncodeContext,
                 match attr.node.value.node {
                   meta_list(_, ref l) => {
                     found_link_attr = true;;
-                    synthesize_link_attr(ecx, /*bad*/copy *l)
+                    synthesize_link_attr(ecx, (*l).clone())
                   }
                   _ => *attr
                 }
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 28866fd568a..62bbe22a043 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -21,8 +21,11 @@ use std::str;
 pub type pick<'self, T> = &'self fn(path: &Path) -> Option<T>;
 
 pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
-    if path.file_path() == file { option::Some(copy *path) }
-    else { option::None }
+    if path.file_path() == file {
+        option::Some((*path).clone())
+    } else {
+        option::None
+    }
 }
 
 pub trait FileSearch {
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 98f7dd766a4..5cf69e26a50 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -55,11 +55,11 @@ pub struct Context {
 
 pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) {
     match find_library_crate(cx) {
-      Some(ref t) => return (/*bad*/copy *t),
+      Some(ref t) => return (/*bad*/(*t).clone()),
       None => {
-        cx.diag.span_fatal(
-            cx.span, fmt!("can't find crate for `%s`",
-                          token::ident_to_str(&cx.ident)));
+        cx.diag.span_fatal(cx.span,
+                           fmt!("can't find crate for `%s`",
+                                token::ident_to_str(&cx.ident)));
       }
     }
 }
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 2cf64f9cb8d..987902d67a8 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -61,7 +61,7 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) {
             Some(&s) => s,
             None => {
                 let s = do io::with_str_writer |wr| {
-                    enc_sty(wr, cx, /*bad*/copy ty::get(t).sty);
+                    enc_sty(wr, cx, &ty::get(t).sty);
                 }.to_managed();
                 cx.tcx.short_names_cache.insert(t, s);
                 s
@@ -75,7 +75,7 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) {
               None => {}
           }
           let pos = w.tell();
-          enc_sty(w, cx, /*bad*/copy ty::get(t).sty);
+          enc_sty(w, cx, &ty::get(t).sty);
           let end = w.tell();
           let len = end - pos;
           fn estimate_sz(u: uint) -> uint {
@@ -221,8 +221,8 @@ pub fn enc_trait_store(w: @io::Writer, cx: @ctxt, s: ty::TraitStore) {
     }
 }
 
-fn enc_sty(w: @io::Writer, cx: @ctxt, st: ty::sty) {
-    match st {
+fn enc_sty(w: @io::Writer, cx: @ctxt, st: &ty::sty) {
+    match *st {
       ty::ty_nil => w.write_char('n'),
       ty::ty_bot => w.write_char('z'),
       ty::ty_bool => w.write_char('b'),
@@ -271,7 +271,7 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, st: ty::sty) {
         enc_bounds(w, cx, &bounds);
         w.write_char(']');
       }
-      ty::ty_tup(ts) => {
+      ty::ty_tup(ref ts) => {
         w.write_str(&"T[");
         for ts.iter().advance |t| { enc_ty(w, cx, *t); }
         w.write_char(']');
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 7684f465a4c..d4d20e75c9d 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -106,7 +106,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
 pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
                            tcx: ty::ctxt,
                            maps: Maps,
-                           path: ast_map::path,
+                           path: &[ast_map::path_elt],
                            par_doc: ebml::Doc)
                         -> Option<ast::inlined_item> {
     let dcx = @DecodeContext {
@@ -134,7 +134,9 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
                ast_map::path_to_str(path, token::get_ident_interner()),
                tcx.sess.str_of(ii.ident()));
         ast_map::map_decoded_item(tcx.sess.diagnostic(),
-                                  dcx.tcx.items, path, &ii);
+                                  dcx.tcx.items,
+                                  path.to_owned(),
+                                  &ii);
         decode_side_tables(xcx, ast_doc);
         match ii {
           ast::ii_item(i) => {
@@ -618,7 +620,7 @@ fn encode_vtable_origin(ecx: &e::EncodeContext,
                     ebml_w.emit_def_id(def_id)
                 }
                 do ebml_w.emit_enum_variant_arg(1u) |ebml_w| {
-                    ebml_w.emit_tys(ecx, /*bad*/copy *tys);
+                    ebml_w.emit_tys(ecx, *tys);
                 }
                 do ebml_w.emit_enum_variant_arg(2u) |ebml_w| {
                     encode_vtable_res(ecx, ebml_w, vtable_res);
@@ -814,7 +816,7 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
                              ebml_w: &mut writer::Encoder,
                              ii: &ast::inlined_item) {
     ebml_w.start_tag(c::tag_table as uint);
-    let new_ebml_w = copy *ebml_w;
+    let new_ebml_w = (*ebml_w).clone();
 
     // Because the ast visitor uses @fn, I can't pass in
     // ecx directly, but /I/ know that it'll be fine since
@@ -827,7 +829,7 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
             // Note: this will cause a copy of ebml_w, which is bad as
             // it is mutable. But I believe it's harmless since we generate
             // balanced EBML.
-            let mut new_ebml_w = copy new_ebml_w;
+            let mut new_ebml_w = new_ebml_w.clone();
             // See above
             let ecx : &e::EncodeContext = unsafe { cast::transmute(ecx_ptr) };
             encode_side_tables_for_id(ecx, maps, &mut new_ebml_w, id)
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 47d35d73df0..d6a373445b7 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -49,6 +49,15 @@ pub mod gather_loans;
 pub mod move_data;
 
 pub struct LoanDataFlowOperator;
+
+/// XXX(pcwalton): Should just be #[deriving(Clone)], but that doesn't work
+/// yet on unit structs.
+impl Clone for LoanDataFlowOperator {
+    fn clone(&self) -> LoanDataFlowOperator {
+        LoanDataFlowOperator
+    }
+}
+
 pub type LoanDataFlow = DataFlowContext<LoanDataFlowOperator>;
 
 pub fn check_crate(
diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs
index 7ec1ff3c628..b96a91f5682 100644
--- a/src/librustc/middle/borrowck/move_data.rs
+++ b/src/librustc/middle/borrowck/move_data.rs
@@ -71,6 +71,12 @@ pub struct FlowedMoveData {
 #[deriving(Eq)]
 pub struct MovePathIndex(uint);
 
+impl Clone for MovePathIndex {
+    fn clone(&self) -> MovePathIndex {
+        MovePathIndex(**self)
+    }
+}
+
 static InvalidMovePathIndex: MovePathIndex =
     MovePathIndex(uint::max_value);
 
@@ -133,9 +139,27 @@ pub struct Assignment {
 }
 
 pub struct MoveDataFlowOperator;
+
+/// XXX(pcwalton): Should just be #[deriving(Clone)], but that doesn't work
+/// yet on unit structs.
+impl Clone for MoveDataFlowOperator {
+    fn clone(&self) -> MoveDataFlowOperator {
+        MoveDataFlowOperator
+    }
+}
+
 pub type MoveDataFlow = DataFlowContext<MoveDataFlowOperator>;
 
 pub struct AssignDataFlowOperator;
+
+/// XXX(pcwalton): Should just be #[deriving(Clone)], but that doesn't work
+/// yet on unit structs.
+impl Clone for AssignDataFlowOperator {
+    fn clone(&self) -> AssignDataFlowOperator {
+        AssignDataFlowOperator
+    }
+}
+
 pub type AssignDataFlow = DataFlowContext<AssignDataFlowOperator>;
 
 impl MoveData {
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 26a03b362e3..f6d23dde143 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -194,20 +194,21 @@ pub fn check_expr(sess: Session,
     visit::visit_expr(e, (is_const, v));
 }
 
+#[deriving(Clone)]
+struct env {
+    root_it: @item,
+    sess: Session,
+    ast_map: ast_map::map,
+    def_map: resolve::DefMap,
+    idstack: @mut ~[node_id]
+}
+
 // Make sure a const item doesn't recursively refer to itself
 // FIXME: Should use the dependency graph when it's available (#1356)
 pub fn check_item_recursion(sess: Session,
                             ast_map: ast_map::map,
                             def_map: resolve::DefMap,
                             it: @item) {
-    struct env {
-        root_it: @item,
-        sess: Session,
-        ast_map: ast_map::map,
-        def_map: resolve::DefMap,
-        idstack: @mut ~[node_id]
-    }
-
     let env = env {
         root_it: it,
         sess: sess,
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index 190602e815d..a8cef8eb276 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -14,6 +14,7 @@ use middle::ty;
 use syntax::ast::*;
 use syntax::visit;
 
+#[deriving(Clone)]
 pub struct Context {
     in_loop: bool,
     can_ret: bool
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 558b184a75a..928e02b9165 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -473,7 +473,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
                   left_ty: ty::t)
                -> Option<~[@pat]> {
     // Sad, but I can't get rid of this easily
-    let r0 = copy *raw_pat(r[0]);
+    let r0 = (*raw_pat(r[0])).clone();
     match r0 {
         pat{id: pat_id, node: n, span: pat_span} =>
             match n {
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 2cf99e07dc9..15e61145262 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -238,7 +238,7 @@ pub fn lookup_const_by_id(tcx: ty::ctxt,
             capture_map: @mut HashMap::new()
         };
         match csearch::maybe_get_item_ast(tcx, def_id,
-            |a, b, c, d| astencode::decode_inlined_item(a, b, maps, /*bar*/ copy c, d)) {
+            |a, b, c, d| astencode::decode_inlined_item(a, b, maps, c, d)) {
             csearch::found(ast::ii_item(item)) => match item.node {
                 item_static(_, ast::m_imm, const_expr) => Some(const_expr),
                 _ => None
@@ -275,7 +275,7 @@ pub fn process_crate(crate: &ast::crate,
 
 // FIXME (#33): this doesn't handle big integer/float literals correctly
 // (nor does the rest of our literal handling).
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum const_val {
     const_float(f64),
     const_int(i64),
@@ -303,7 +303,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &expr)
           Ok(const_uint(i)) => Ok(const_uint(-i)),
           Ok(const_str(_)) => Err(~"Negate on string"),
           Ok(const_bool(_)) => Err(~"Negate on boolean"),
-          ref err => (/*bad*/copy *err)
+          ref err => ((*err).clone())
         }
       }
       expr_unary(_, not, inner) => {
@@ -410,28 +410,34 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &expr)
       expr_cast(base, _) => {
         let ety = tcx.expr_ty(e);
         let base = eval_const_expr_partial(tcx, base);
-        match /*bad*/copy base {
+        match base {
             Err(_) => base,
             Ok(val) => {
                 match ty::get(ety).sty {
-                    ty::ty_float(_) => match val {
-                        const_uint(u) => Ok(const_float(u as f64)),
-                        const_int(i) => Ok(const_float(i as f64)),
-                        const_float(_) => base,
-                        _ => Err(~"Can't cast float to str"),
-                    },
-                    ty::ty_uint(_) => match val {
-                        const_uint(_) => base,
-                        const_int(i) => Ok(const_uint(i as u64)),
-                        const_float(f) => Ok(const_uint(f as u64)),
-                        _ => Err(~"Can't cast str to uint"),
-                    },
-                    ty::ty_int(_) | ty::ty_bool => match val {
-                        const_uint(u) => Ok(const_int(u as i64)),
-                        const_int(_) => base,
-                        const_float(f) => Ok(const_int(f as i64)),
-                        _ => Err(~"Can't cast str to int"),
-                    },
+                    ty::ty_float(_) => {
+                        match val {
+                            const_uint(u) => Ok(const_float(u as f64)),
+                            const_int(i) => Ok(const_float(i as f64)),
+                            const_float(f) => Ok(const_float(f)),
+                            _ => Err(~"Can't cast float to str"),
+                        }
+                    }
+                    ty::ty_uint(_) => {
+                        match val {
+                            const_uint(u) => Ok(const_uint(u)),
+                            const_int(i) => Ok(const_uint(i as u64)),
+                            const_float(f) => Ok(const_uint(f as u64)),
+                            _ => Err(~"Can't cast str to uint"),
+                        }
+                    }
+                    ty::ty_int(_) | ty::ty_bool => {
+                        match val {
+                            const_uint(u) => Ok(const_int(u as i64)),
+                            const_int(i) => Ok(const_int(i)),
+                            const_float(f) => Ok(const_int(f as i64)),
+                            _ => Err(~"Can't cast str to int"),
+                        }
+                    }
                     _ => Err(~"Can't cast this type")
                 }
             }
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 8c464928b58..62d1b552691 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -30,6 +30,7 @@ use middle::ty;
 use middle::typeck;
 use util::ppaux::Repr;
 
+#[deriving(Clone)]
 pub struct DataFlowContext<O> {
     priv tcx: ty::ctxt,
     priv method_map: typeck::method_map,
@@ -294,8 +295,8 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
     }
 }
 
-impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
-//                      ^^^^^^^^^^^^ only needed for pretty printing
+impl<O:DataFlowOperator+Clone+'static> DataFlowContext<O> {
+//                      ^^^^^^^^^^^^^ only needed for pretty printing
     pub fn propagate(&mut self, blk: &ast::blk) {
         //! Performs the data flow analysis.
 
@@ -304,23 +305,25 @@ impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
             return;
         }
 
-        let mut propcx = PropagationContext {
-            dfcx: self,
-            changed: true
-        };
+        {
+            let mut propcx = PropagationContext {
+                dfcx: self,
+                changed: true
+            };
 
-        let mut temp = vec::from_elem(self.words_per_id, 0);
-        let mut loop_scopes = ~[];
+            let mut temp = vec::from_elem(self.words_per_id, 0u);
+            let mut loop_scopes = ~[];
 
-        while propcx.changed {
-            propcx.changed = false;
-            propcx.reset(temp);
-            propcx.walk_block(blk, temp, &mut loop_scopes);
+            while propcx.changed {
+                propcx.changed = false;
+                propcx.reset(temp);
+                propcx.walk_block(blk, temp, &mut loop_scopes);
+            }
         }
 
         debug!("Dataflow result:");
         debug!("%s", {
-            let this = @copy *self;
+            let this = @(*self).clone();
             this.pretty_print_to(io::stderr(), blk);
             ""
         });
@@ -897,7 +900,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
         // statement.
         let initial_state = reslice(in_out).to_owned();
         for pats.iter().advance |&pat| {
-            let mut temp = copy initial_state;
+            let mut temp = initial_state.clone();
             self.walk_pat(pat, temp, loop_scopes);
             join_bits(&self.dfcx.oper, temp, in_out);
         }
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
index ee7c35fb3d5..0bbe674d821 100644
--- a/src/librustc/middle/freevars.rs
+++ b/src/librustc/middle/freevars.rs
@@ -79,7 +79,7 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::blk)
                                           visit_expr: walk_expr,
                                           .. *visit::default_visitor()});
     (v.visit_block)(blk, (1, v));
-    return @/*bad*/copy *refs;
+    return @(*refs).clone();
 }
 
 // Build a map from every function and for-each body to a set of the
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index cce5a9d85f5..6d9a15a3c34 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -53,6 +53,7 @@ use syntax::{visit, ast_util};
 
 pub static try_adding: &'static str = "Try adding a move";
 
+#[deriving(Clone)]
 pub struct Context {
     tcx: ty::ctxt,
     method_map: typeck::method_map,
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 992eb28bda8..0e4b2805cce 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -67,7 +67,7 @@ use syntax::{ast, visit, ast_util};
  * item that's being warned about.
  */
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum lint {
     ctypes,
     unused_imports,
@@ -109,7 +109,7 @@ pub fn level_to_str(lv: level) -> &'static str {
     }
 }
 
-#[deriving(Eq, Ord)]
+#[deriving(Clone, Eq, Ord)]
 pub enum level {
     allow, warn, deny, forbid
 }
@@ -652,8 +652,11 @@ fn lint_type_limits() -> visit::vt<@mut Context> {
         }
     }
 
-    fn check_limits(cx: &Context, binop: ast::binop, l: &ast::expr,
-                    r: &ast::expr) -> bool {
+    fn check_limits(cx: &Context,
+                    binop: ast::binop,
+                    l: @ast::expr,
+                    r: @ast::expr)
+                    -> bool {
         let (lit, expr, swap) = match (&l.node, &r.node) {
             (&ast::expr_lit(_), _) => (l, r, true),
             (_, &ast::expr_lit(_)) => (r, l, false),
@@ -666,7 +669,7 @@ fn lint_type_limits() -> visit::vt<@mut Context> {
         } else {
             binop
         };
-        match ty::get(ty::expr_ty(cx.tcx, @/*bad*/copy *expr)).sty {
+        match ty::get(ty::expr_ty(cx.tcx, expr)).sty {
             ty::ty_int(int_ty) => {
                 let (min, max) = int_ty_range(int_ty);
                 let lit_val: i64 = match lit.node {
@@ -708,7 +711,7 @@ fn lint_type_limits() -> visit::vt<@mut Context> {
     visit::mk_vt(@visit::Visitor {
         visit_expr: |e, (cx, vt): (@mut Context, visit::vt<@mut Context>)| {
             match e.node {
-                ast::expr_binary(_, ref binop, @ref l, @ref r) => {
+                ast::expr_binary(_, ref binop, l, r) => {
                     if is_comparison(*binop)
                         && !check_limits(cx, *binop, l, r) {
                         cx.span_lint(type_limits, e.span,
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index f0ad8a339b1..689a4931b37 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -128,6 +128,12 @@ struct Variable(uint);
 #[deriving(Eq)]
 struct LiveNode(uint);
 
+impl Clone for LiveNode {
+    fn clone(&self) -> LiveNode {
+        LiveNode(**self)
+    }
+}
+
 #[deriving(Eq)]
 enum LiveNodeKind {
     FreeVarNode(span),
@@ -522,6 +528,7 @@ fn visit_expr(expr: @expr, (this, vt): (@mut IrMaps, vt<@mut IrMaps>)) {
 // Actually we compute just a bit more than just liveness, but we use
 // the same basic propagation framework in all cases.
 
+#[deriving(Clone)]
 struct Users {
     reader: LiveNode,
     writer: LiveNode,
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index d569f852612..79d7f397bb2 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -170,12 +170,14 @@ pub type MovesMap = @mut HashSet<node_id>;
 pub type MovedVariablesSet = @mut HashSet<node_id>;
 
 /** See the section Output on the module comment for explanation. */
+#[deriving(Clone)]
 pub struct MoveMaps {
     moves_map: MovesMap,
     moved_variables_set: MovedVariablesSet,
     capture_map: CaptureMap
 }
 
+#[deriving(Clone)]
 struct VisitContext {
     tcx: ty::ctxt,
     method_map: method_map,
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 0a13cf4ed18..036c0751483 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -376,7 +376,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
         visit_item: |item, (method_map, visitor)| {
             // Do not check privacy inside items with the resolve_unexported
             // attribute. This is used for the test runner.
-            if !attr::contains_name(attr::attr_metas(/*bad*/copy item.attrs),
+            if !attr::contains_name(attr::attr_metas(item.attrs),
                                     "!resolve_unexported") {
                 visit::visit_item(item, (method_map, visitor));
             }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 70833813cc0..a0ba9ac5a88 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -76,7 +76,7 @@ fn trait_method_might_be_inlined(trait_method: &trait_method) -> bool {
 // The context we're in. If we're in a public context, then public symbols are
 // marked reachable. If we're in a private context, then only trait
 // implementations are marked reachable.
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 enum PrivacyContext {
     PublicContext,
     PrivateContext,
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index d1ada030da4..69c22ee5220 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -60,6 +60,7 @@ pub struct RegionMaps {
     priv cleanup_scopes: HashSet<ast::node_id>
 }
 
+#[deriving(Clone)]
 pub struct Context {
     sess: Session,
     def_map: resolve::DefMap,
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index cd846067a95..80078eba239 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -158,6 +158,7 @@ pub enum ImportDirectiveSubclass {
 }
 
 /// The context that we thread through while building the reduced graph.
+#[deriving(Clone)]
 pub enum ReducedGraphParent {
     ModuleReducedGraphParent(@mut Module)
 }
@@ -1483,12 +1484,13 @@ impl Resolver {
                             for source_idents.iter().advance |source_ident| {
                                 let name = source_ident.node.name;
                                 let subclass = @SingleImport(name, name);
-                                self.build_import_directive(privacy,
-                                                            module_,
-                                                            copy module_path,
-                                                            subclass,
-                                                            source_ident.span,
-                                                            source_ident.node.id);
+                                self.build_import_directive(
+                                    privacy,
+                                    module_,
+                                    module_path.clone(),
+                                    subclass,
+                                    source_ident.span,
+                                    source_ident.node.id);
                             }
                         }
                         view_path_glob(_, id) => {
@@ -5165,13 +5167,13 @@ impl Resolver {
         match self.method_map.find(&name) {
             Some(candidate_traits) => loop {
                 // Look for the current trait.
-                match /*bad*/copy self.current_trait_refs {
-                    Some(trait_def_ids) => {
+                match self.current_trait_refs {
+                    Some(ref trait_def_ids) => {
                         for trait_def_ids.iter().advance |trait_def_id| {
                             if candidate_traits.contains(trait_def_id) {
-                                self.add_trait_info(
-                                    &mut found_traits,
-                                    *trait_def_id, name);
+                                self.add_trait_info(&mut found_traits,
+                                                    *trait_def_id,
+                                                    name);
                             }
                         }
                     }
@@ -5428,10 +5430,9 @@ pub fn resolve_crate(session: Session,
                   -> CrateMap {
     let resolver = @mut Resolver(session, lang_items, crate);
     resolver.resolve();
-    let Resolver { def_map, export_map2, trait_map, _ } = copy *resolver;
     CrateMap {
-        def_map: def_map,
-        exp_map2: export_map2,
-        trait_map: trait_map
+        def_map: resolver.def_map,
+        exp_map2: resolver.export_map2,
+        trait_map: resolver.trait_map.clone(),
     }
 }
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 2f27949e869..718bb4c9e20 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -76,7 +76,7 @@
  *
  *    let a: A = ...;
  *    let b: B = ...;
- *    match (a, b) { (ref c, copy d) => { ... } }
+ *    match (a, b) { (ref c, d) => { ... } }
  *
  * For `c` and `d`, we would generate allocas of type `C*` and `D*`
  * respectively.  These are called the `llmatch`.  As we match, when we come
@@ -540,9 +540,10 @@ pub fn enter_opt<'r>(bcx: block,
             }
             ast::pat_enum(_, ref subpats) => {
                 if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
+                    // XXX: Must we clone?
                     match *subpats {
                         None => Some(vec::from_elem(variant_size, dummy)),
-                        _ => copy *subpats
+                        _ => (*subpats).clone(),
                     }
                 } else {
                     None
@@ -597,7 +598,7 @@ pub fn enter_opt<'r>(bcx: block,
                         let n = before.len() + after.len();
                         let i = before.len();
                         if opt_eq(tcx, &vec_len_ge(n, i), opt) {
-                            Some(vec::append_one(copy *before, slice) +
+                            Some(vec::append_one((*before).clone(), slice) +
                                     *after)
                         } else {
                             None
@@ -606,7 +607,7 @@ pub fn enter_opt<'r>(bcx: block,
                     None => {
                         let n = before.len();
                         if opt_eq(tcx, &vec_len_eq(n), opt) {
-                            Some(copy *before)
+                            Some((*before).clone())
                         } else {
                             None
                         }
@@ -673,9 +674,7 @@ pub fn enter_tup<'r>(bcx: block,
     let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
     do enter_match(bcx, dm, m, col, val) |p| {
         match p.node {
-            ast::pat_tup(ref elts) => {
-                Some(copy *elts)
-            }
+            ast::pat_tup(ref elts) => Some((*elts).clone()),
             _ => {
                 assert_is_binding_or_wild(bcx, p);
                 Some(vec::from_elem(n_elts, dummy))
@@ -701,7 +700,7 @@ pub fn enter_tuple_struct<'r>(bcx: block,
     let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
     do enter_match(bcx, dm, m, col, val) |p| {
         match p.node {
-            ast::pat_enum(_, Some(ref elts)) => Some(copy *elts),
+            ast::pat_enum(_, Some(ref elts)) => Some((*elts).clone()),
             _ => {
                 assert_is_binding_or_wild(bcx, p);
                 Some(vec::from_elem(n_elts, dummy))
@@ -1582,7 +1581,7 @@ pub fn compile_submatch(bcx: block,
                 let args = extract_vec_elems(opt_cx, pat_span, pat_id, n, slice,
                                              val, test_val);
                 size = args.vals.len();
-                unpacked = /*bad*/copy args.vals;
+                unpacked = args.vals.clone();
                 opt_cx = args.bcx;
             }
             lit(_) | range(_, _) => ()
@@ -1606,7 +1605,7 @@ pub fn compile_submatch(bcx: block,
 pub fn trans_match(bcx: block,
                    match_expr: &ast::expr,
                    discr_expr: @ast::expr,
-                   arms: ~[ast::arm],
+                   arms: &[ast::arm],
                    dest: Dest) -> block {
     let _icx = push_ctxt("match::trans_match");
     do with_scope(bcx, match_expr.info(), "match") |bcx| {
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 0a2d24ee5ff..821242d64c9 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -191,9 +191,11 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
                             Some(ptrfield) => {
                                 return NullablePointer {
                                     nndiscr: discr,
-                                    nonnull: mk_struct(cx, cases[discr].tys, false),
+                                    nonnull: mk_struct(cx,
+                                                       cases[discr].tys,
+                                                       false),
                                     ptrfield: ptrfield,
-                                    nullfields: copy cases[1 - discr].tys
+                                    nullfields: cases[1 - discr].tys.clone()
                                 }
                             }
                             None => { }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index c9631f03475..9d8bac6467e 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -112,7 +112,7 @@ impl Drop for _InsnCtxt {
     fn drop(&self) {
         do local_data::modify(task_local_insn_key) |c| {
             do c.map_consume |ctx| {
-                let mut ctx = copy *ctx;
+                let mut ctx = (*ctx).clone();
                 ctx.pop();
                 @ctx
             }
@@ -124,7 +124,7 @@ pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
     debug!("new InsnCtxt: %s", s);
     do local_data::modify(task_local_insn_key) |c| {
         do c.map_consume |ctx| {
-            let mut ctx = copy *ctx;
+            let mut ctx = (*ctx).clone();
             ctx.push(s);
             @ctx
         }
@@ -1413,7 +1413,7 @@ pub fn with_scope(bcx: block,
     let scope = simple_block_scope(bcx.scope, opt_node_info);
     bcx.scope = Some(scope);
     let ret = f(bcx);
-    let ret = trans_block_cleanups_(ret, /*bad*/copy scope.cleanups, false);
+    let ret = trans_block_cleanups_(ret, (scope.cleanups).clone(), false);
     bcx.scope = scope.parent;
     ret
 }
@@ -1427,7 +1427,9 @@ pub fn with_scope_result(bcx: block,
     let scope = simple_block_scope(bcx.scope, opt_node_info);
     bcx.scope = Some(scope);
     let Result { bcx: out_bcx, val } = f(bcx);
-    let out_bcx = trans_block_cleanups_(out_bcx, /*bad*/copy scope.cleanups, false);
+    let out_bcx = trans_block_cleanups_(out_bcx,
+                                        (scope.cleanups).clone(),
+                                        false);
     bcx.scope = scope.parent;
 
     rslt(out_bcx, val)
@@ -1932,7 +1934,7 @@ pub fn trans_fn(ccx: @mut CrateContext,
     let _icx = push_ctxt("trans_fn");
     let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
     trans_closure(ccx,
-                  copy path,
+                  path.clone(),
                   decl,
                   body,
                   llfndecl,
@@ -2038,7 +2040,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
     let fn_args = do args.map |varg| {
         ast::arg {
             is_mutbl: false,
-            ty: copy *varg.ty(),
+            ty: (*varg.ty()).clone(),
             pat: ast_util::ident_to_pat(
                 ccx.tcx.sess.next_node_id(),
                 codemap::dummy_sp(),
@@ -2047,12 +2049,21 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
         }
     };
 
+    let no_substs: &[ty::t] = [];
     let ty_param_substs = match param_substs {
-        Some(ref substs) => { copy substs.tys }
-        None => ~[]
+        Some(ref substs) => {
+            let v: &[ty::t] = substs.tys;
+            v
+        }
+        None => {
+            let v: &[ty::t] = no_substs;
+            v
+        }
     };
 
-    let ctor_ty = ty::subst_tps(ccx.tcx, ty_param_substs, None,
+    let ctor_ty = ty::subst_tps(ccx.tcx,
+                                ty_param_substs,
+                                None,
                                 ty::node_id_to_type(ccx.tcx, ctor_id));
 
     let result_ty = match ty::get(ctor_ty).sty {
@@ -2130,7 +2141,7 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
         if purity == ast::extern_fn  {
             let llfndecl = get_item_val(ccx, item.id);
             foreign::trans_foreign_fn(ccx,
-                                      vec::append(/*bad*/copy *path,
+                                      vec::append((*path).clone(),
                                                   [path_name(item.ident)]),
                                       decl,
                                       body,
@@ -2139,7 +2150,7 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
         } else if !generics.is_type_parameterized() {
             let llfndecl = get_item_val(ccx, item.id);
             trans_fn(ccx,
-                     vec::append(/*bad*/copy *path, [path_name(item.ident)]),
+                     vec::append((*path).clone(), [path_name(item.ident)]),
                      decl,
                      body,
                      llfndecl,
@@ -2160,8 +2171,12 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
         }
       }
       ast::item_impl(ref generics, _, _, ref ms) => {
-        meth::trans_impl(ccx, /*bad*/copy *path, item.ident, *ms,
-                         generics, item.id);
+        meth::trans_impl(ccx,
+                         (*path).clone(),
+                         item.ident,
+                         *ms,
+                         generics,
+                         item.id);
       }
       ast::item_mod(ref m) => {
         trans_mod(ccx, m);
@@ -2274,7 +2289,7 @@ pub fn register_fn_fuller(ccx: @mut CrateContext,
     let ps = if attr::attrs_contains_name(attrs, "no_mangle") {
         path_elt_to_str(*path.last(), token::get_ident_interner())
     } else {
-        mangle_exported_name(ccx, /*bad*/copy path, node_type)
+        mangle_exported_name(ccx, path, node_type)
     };
 
     let llfn = decl_fn(ccx.llmod, ps, cc, fn_ty);
@@ -2432,7 +2447,7 @@ pub fn item_path(ccx: &CrateContext, i: &ast::item) -> path {
             // separate map for paths?
         _ => fail!("item_path")
     };
-    vec::append(/*bad*/copy *base, [path_name(i.ident)])
+    vec::append((*base).clone(), [path_name(i.ident)])
 }
 
 pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
@@ -2445,8 +2460,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
         let item = ccx.tcx.items.get_copy(&id);
         let val = match item {
           ast_map::node_item(i, pth) => {
-            let my_path = vec::append(/*bad*/copy *pth,
-                                      [path_name(i.ident)]);
+            let my_path = vec::append((*pth).clone(), [path_name(i.ident)]);
             match i.node {
               ast::item_static(_, m, expr) => {
                 let typ = ty::node_id_to_type(ccx.tcx, i.id);
@@ -2502,7 +2516,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
             match ni.node {
                 ast::foreign_item_fn(*) => {
                     register_fn(ccx, ni.span,
-                                vec::append(/*bad*/copy *pth,
+                                vec::append((*pth).clone(),
                                             [path_name(ni.ident)]),
                                 ni.id,
                                 ni.attrs)
@@ -2526,7 +2540,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
             match v.node.kind {
                 ast::tuple_variant_kind(ref args) => {
                     assert!(args.len() != 0u);
-                    let pth = vec::append(/*bad*/copy *pth,
+                    let pth = vec::append((*pth).clone(),
                                           [path_name(enm.ident),
                                            path_name((*v).node.name)]);
                     llfn = match enm.node {
@@ -2554,7 +2568,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
                 Some(ctor_id) => {
                     let llfn = register_fn(ccx,
                                            struct_item.span,
-                                           /*bad*/copy *struct_path,
+                                           (*struct_path).clone(),
                                            ctor_id,
                                            struct_item.attrs);
                     set_inline_hint(llfn);
@@ -2583,7 +2597,7 @@ pub fn register_method(ccx: @mut CrateContext,
                        m: @ast::method) -> ValueRef {
     let mty = ty::node_id_to_type(ccx.tcx, id);
 
-    let mut path = /*bad*/ copy *path;
+    let mut path = (*path).clone();
     path.push(path_name(gensym_name("meth")));
     path.push(path_name(m.ident));
 
@@ -2603,7 +2617,7 @@ pub fn trans_constant(ccx: &mut CrateContext, it: @ast::item) {
         let mut i = 0;
         let path = item_path(ccx, it);
         for (*enum_definition).variants.iter().advance |variant| {
-            let p = vec::append(/*bad*/copy path, [
+            let p = vec::append(path.clone(), [
                 path_name(variant.node.name),
                 path_name(special_idents::descrim)
             ]);
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index ddac647dced..26fce42f8e3 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -897,7 +897,7 @@ pub fn add_span_comment(bcx: block, sp: span, text: &str) {
     let ccx = bcx.ccx();
     if ccx.sess.asm_comments() {
         let s = fmt!("%s (%s)", text, ccx.sess.codemap.span_to_str(sp));
-        debug!("%s", copy s);
+        debug!("%s", s);
         add_comment(bcx, s);
     }
 }
diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs
index 8d741369e1a..b7e157bc7e2 100644
--- a/src/librustc/middle/trans/cabi.rs
+++ b/src/librustc/middle/trans/cabi.rs
@@ -22,6 +22,7 @@ pub trait ABIInfo {
     fn compute_info(&self, atys: &[Type], rty: Type, ret_def: bool) -> FnType;
 }
 
+#[deriving(Clone)]
 pub struct LLVMType {
     cast: bool,
     ty: Type
diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs
index 6a0387d14ea..fb09c8994ce 100644
--- a/src/librustc/middle/trans/cabi_x86_64.rs
+++ b/src/librustc/middle/trans/cabi_x86_64.rs
@@ -24,7 +24,7 @@ use std::option::Option;
 use std::uint;
 use std::vec;
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 enum RegClass {
     NoClass,
     Int,
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 337f5b2bbad..0885c5086e8 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -221,7 +221,7 @@ fn resolve_default_method_vtables(bcx: block,
     // Build up a param_substs that we are going to resolve the
     // trait_vtables under.
     let param_substs = Some(@param_substs {
-        tys: copy substs.tps,
+        tys: substs.tps.clone(),
         self_ty: substs.self_ty,
         vtables: impl_vtables,
         self_vtable: None
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 01347af63ef..6b10d53dd41 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -423,11 +423,11 @@ pub fn trans_expr_fn(bcx: block,
 
     let llfnty = type_of_fn_from_ty(ccx, fty);
 
-    let sub_path = vec::append_one(/*bad*/copy bcx.fcx.path,
+    let sub_path = vec::append_one(bcx.fcx.path.clone(),
                                    path_name(special_idents::anon));
     // XXX: Bad copy.
     let s = mangle_internal_name_by_path_and_seq(ccx,
-                                                 copy sub_path,
+                                                 sub_path.clone(),
                                                  "expr_fn");
     let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
 
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index f7bdf9d5aac..29cc8d81973 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -287,7 +287,7 @@ pub enum heap {
     heap_exchange_closure
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum cleantype {
     normal_exit_only,
     normal_exit_and_unwind
@@ -298,8 +298,19 @@ pub enum cleanup {
     clean_temp(ValueRef, @fn(block) -> block, cleantype),
 }
 
+// Can't use deriving(Clone) because of the managed closure.
+impl Clone for cleanup {
+    fn clone(&self) -> cleanup {
+        match *self {
+            clean(f, ct) => clean(f, ct),
+            clean_temp(v, f, ct) => clean_temp(v, f, ct),
+        }
+    }
+}
+
 // Used to remember and reuse existing cleanup paths
 // target: none means the path ends in an resume instruction
+#[deriving(Clone)]
 pub struct cleanup_path {
     target: Option<BasicBlockRef>,
     size: uint,
@@ -441,7 +452,7 @@ pub fn revoke_clean(cx: block, val: ValueRef) {
 pub fn block_cleanups(bcx: block) -> ~[cleanup] {
     match bcx.scope {
        None  => ~[],
-       Some(inf) => /*bad*/copy inf.cleanups
+       Some(inf) => inf.cleanups.clone(),
     }
 }
 
@@ -1036,7 +1047,9 @@ pub fn resolve_vtables_under_param_substs(tcx: ty::ctxt,
     -> typeck::vtable_res {
     @vts.iter().transform(|ds|
       @ds.iter().transform(
-          |d| resolve_vtable_under_param_substs(tcx, param_substs, copy *d))
+          |d| resolve_vtable_under_param_substs(tcx,
+                                                param_substs,
+                                                d))
                           .collect::<~[typeck::vtable_origin]>())
         .collect::<~[typeck::vtable_param_res]>()
 }
@@ -1044,7 +1057,7 @@ pub fn resolve_vtables_under_param_substs(tcx: ty::ctxt,
 
 // Apply the typaram substitutions in the fn_ctxt to a vtable. This should
 // eliminate any vtable_params.
-pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
+pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: &typeck::vtable_origin)
     -> typeck::vtable_origin {
     resolve_vtable_under_param_substs(fcx.ccx.tcx,
                                       fcx.param_substs,
@@ -1053,17 +1066,17 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
 
 pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
                                          param_substs: Option<@param_substs>,
-                                         vt: typeck::vtable_origin)
-    -> typeck::vtable_origin {
-    match vt {
-        typeck::vtable_static(trait_id, tys, sub) => {
+                                         vt: &typeck::vtable_origin)
+                                         -> typeck::vtable_origin {
+    match *vt {
+        typeck::vtable_static(trait_id, ref tys, sub) => {
             let tys = match param_substs {
                 Some(substs) => {
                     do tys.iter().transform |t| {
                         ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
                     }.collect()
                 }
-                _ => tys
+                _ => tys.to_owned()
             };
             typeck::vtable_static(
                 trait_id, tys,
@@ -1085,7 +1098,7 @@ pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
             match param_substs {
                 Some(@param_substs
                      {self_vtable: Some(ref self_vtable), _}) => {
-                    copy *self_vtable
+                    (*self_vtable).clone()
                 }
                 _ => {
                     tcx.sess.bug(fmt!(
@@ -1097,13 +1110,15 @@ pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
     }
 }
 
-pub fn find_vtable(tcx: ty::ctxt, ps: &param_substs,
-                   n_param: uint, n_bound: uint)
-    -> typeck::vtable_origin {
+pub fn find_vtable(tcx: ty::ctxt,
+                   ps: &param_substs,
+                   n_param: uint,
+                   n_bound: uint)
+                   -> typeck::vtable_origin {
     debug!("find_vtable(n_param=%u, n_bound=%u, ps=%s)",
            n_param, n_bound, ps.repr(tcx));
 
-    /*bad*/ copy ps.vtables.get()[n_param][n_bound]
+    ps.vtables.get()[n_param][n_bound].clone()
 }
 
 pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index fc73d805379..00b59d187bf 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -816,8 +816,8 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType {
 
     debug!("create_ty: %?", ty::get(t));
 
-    let sty = copy ty::get(t).sty;
-    let ty_md = match sty {
+    let sty = &ty::get(t).sty;
+    let ty_md = match *sty {
         ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_)
         | ty::ty_float(_) => create_basic_type(cx, t, span),
         ty::ty_estr(ref vstore) => {
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 72e9f272468..b92f43b1c8d 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -570,8 +570,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
             return controlflow::trans_if(bcx, cond, thn, els, dest);
         }
         ast::expr_match(discr, ref arms) => {
-            return _match::trans_match(bcx, expr, discr, /*bad*/copy *arms,
-                                       dest);
+            return _match::trans_match(bcx, expr, discr, *arms, dest);
         }
         ast::expr_block(ref blk) => {
             return do base::with_scope(bcx, blk.info(),
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index edf003e3e52..bebed1c3d0d 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -109,7 +109,7 @@ fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig)
 
 fn shim_types(ccx: @mut CrateContext, id: ast::node_id) -> ShimTypes {
     let fn_sig = match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty {
-        ty::ty_bare_fn(ref fn_ty) => copy fn_ty.sig,
+        ty::ty_bare_fn(ref fn_ty) => fn_ty.sig.clone(),
         _ => ccx.sess.bug("c_arg_and_ret_lltys called on non-function type")
     };
     let llsig = foreign_signature(ccx, &fn_sig);
@@ -1163,7 +1163,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
     let _icx = push_ctxt("foreign::build_foreign_fn");
 
     fn build_rust_fn(ccx: @mut CrateContext,
-                     path: ast_map::path,
+                     path: &ast_map::path,
                      decl: &ast::fn_decl,
                      body: &ast::blk,
                      id: ast::node_id)
@@ -1172,13 +1172,14 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
         let t = ty::node_id_to_type(ccx.tcx, id);
         // XXX: Bad copy.
         let ps = link::mangle_internal_name_by_path(
-            ccx, vec::append_one(copy path, ast_map::path_name(
-                special_idents::clownshoe_abi
-            )));
+                            ccx,
+                            vec::append_one((*path).clone(),
+                                            ast_map::path_name(
+                                            special_idents::clownshoe_abi)));
         let llty = type_of_fn_from_ty(ccx, t);
         let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty);
         trans_fn(ccx,
-                 path,
+                 (*path).clone(),
                  decl,
                  body,
                  llfndecl,
@@ -1318,7 +1319,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
     let tys = shim_types(ccx, id);
     // The internal Rust ABI function - runs on the Rust stack
     // XXX: Bad copy.
-    let llrustfn = build_rust_fn(ccx, copy path, decl, body, id);
+    let llrustfn = build_rust_fn(ccx, &path, decl, body, id);
     // The internal shim function - runs on the Rust stack
     let llshimfn = build_shim_fn(ccx, path, llrustfn, &tys);
     // The foreign C function - runs on the C stack
@@ -1337,9 +1338,10 @@ pub fn register_foreign_fn(ccx: @mut CrateContext,
 
     let tys = shim_types(ccx, node_id);
     do tys.fn_ty.decl_fn |fnty| {
+        // XXX(pcwalton): We should not copy the path.
         register_fn_fuller(ccx,
                            sp,
-                           /*bad*/copy path,
+                           path.clone(),
                            node_id,
                            attrs,
                            t,
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index c92bfc23b1d..b717445a22f 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -426,7 +426,7 @@ pub fn trans_struct_drop_flag(bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast:
 
         // Find and call the actual destructor
         let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did,
-                                     class_did, /*bad*/copy substs.tps);
+                                     class_did, substs.tps.clone());
 
         // The second argument is the "self" argument for drop
         let params = unsafe {
@@ -461,7 +461,7 @@ pub fn trans_struct_drop(mut bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::
 
     // Find and call the actual destructor
     let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did,
-                                 class_did, /*bad*/copy substs.tps);
+                                 class_did, substs.tps.clone());
 
     // The second argument is the "self" argument for drop
     let params = unsafe {
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index e2d84473e23..c91be89b30b 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -44,8 +44,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id)
         csearch::maybe_get_item_ast(
             ccx.tcx, fn_id,
             |a,b,c,d| {
-                astencode::decode_inlined_item(a, b, ccx.maps,
-                                               /*bad*/ copy c, d)
+                astencode::decode_inlined_item(a, b, ccx.maps, c.clone(), d)
             });
     return match csearch_result {
         csearch::not_found => {
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 4c401af8e8e..4ca8057f388 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -60,7 +60,7 @@ pub fn trans_impl(ccx: @mut CrateContext,
     for methods.iter().advance |method| {
         if method.generics.ty_params.len() == 0u {
             let llfn = get_item_val(ccx, method.id);
-            let path = vec::append_one(/*bad*/copy sub_path,
+            let path = vec::append_one(sub_path.clone(),
                                        path_name(method.ident));
 
             trans_method(ccx,
@@ -72,18 +72,17 @@ pub fn trans_impl(ccx: @mut CrateContext,
     }
 }
 
-/**
-Translates a (possibly monomorphized) method body.
-
-# Parameters
-
-- `path`: the path to the method
-- `method`: the AST node for the method
-- `param_substs`: if this is a generic method, the current values for
-  type parameters and so forth, else none
-- `llfn`: the LLVM ValueRef for the method
-- `impl_id`: the node ID of the impl this method is inside
-*/
+/// Translates a (possibly monomorphized) method body.
+///
+/// Parameters:
+/// * `path`: the path to the method
+/// * `method`: the AST node for the method
+/// * `param_substs`: if this is a generic method, the current values for
+///   type parameters and so forth, else none
+/// * `llfn`: the LLVM ValueRef for the method
+/// * `impl_id`: the node ID of the impl this method is inside
+///
+/// XXX(pcwalton) Can we take `path` by reference?
 pub fn trans_method(ccx: @mut CrateContext,
                     path: path,
                     method: &ast::method,
@@ -226,9 +225,13 @@ pub fn trans_method_callee(bcx: block,
             match bcx.fcx.param_substs {
                 Some(@param_substs
                      {self_vtable: Some(ref vtbl), _}) => {
-                    trans_monomorphized_callee(bcx, callee_id, this, mentry,
-                                               trait_id, method_index,
-                                               copy *vtbl)
+                    trans_monomorphized_callee(bcx,
+                                               callee_id,
+                                               this,
+                                               mentry,
+                                               trait_id,
+                                               method_index,
+                                               (*vtbl).clone())
                 }
                 _ => {
                     fail!("trans_method_callee: missing self_vtable")
@@ -503,7 +506,7 @@ pub fn trans_trait_callee(bcx: block,
                           self_expr: @ast::expr,
                           store: ty::TraitStore,
                           explicit_self: ast::explicit_self_)
-                       -> Callee {
+                          -> Callee {
     //!
     //
     // Create a method callee where the method is coming from a trait
@@ -646,7 +649,7 @@ pub fn vtable_id(ccx: @mut CrateContext,
     match origin {
         &typeck::vtable_static(impl_id, ref substs, sub_vtables) => {
             let psubsts = param_substs {
-                tys: copy *substs,
+                tys: (*substs).clone(),
                 vtables: Some(sub_vtables),
                 self_ty: None,
                 self_vtable: None
@@ -733,7 +736,7 @@ pub fn make_impl_vtable(bcx: block,
         let fty = ty::subst_tps(tcx,
                                 substs,
                                 None,
-                                ty::mk_bare_fn(tcx, copy im.fty));
+                                ty::mk_bare_fn(tcx, im.fty.clone()));
         if im.generics.has_type_params() || ty::type_has_self(fty) {
             debug!("(making impl vtable) method has self or type params: %s",
                    tcx.sess.str_of(im.ident));
@@ -784,8 +787,8 @@ pub fn trans_trait_cast(bcx: block,
     bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
 
     // Store the vtable into the pair or triple.
-    let orig = /*bad*/copy ccx.maps.vtable_map.get(&id)[0][0];
-    let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, orig);
+    let orig = ccx.maps.vtable_map.get(&id)[0][0].clone();
+    let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, &orig);
     let vtable = get_vtable(bcx, v_ty, orig);
     Store(bcx, vtable, PointerCast(bcx,
                                    GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index d3fc8ec670a..3e5f7267972 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -210,13 +210,13 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
     ccx.monomorphizing.insert(fn_id, depth + 1);
 
     let elt = path_name(gensym_name(ccx.sess.str_of(name)));
-    let mut pt = /* bad */copy (*pt);
+    let mut pt = (*pt).clone();
     pt.push(elt);
-    let s = mangle_exported_name(ccx, /*bad*/copy pt, mono_ty);
+    let s = mangle_exported_name(ccx, pt.clone(), mono_ty);
     debug!("monomorphize_fn mangled to %s", s);
 
     let mk_lldecl = || {
-        let lldecl = decl_internal_cdecl_fn(ccx.llmod, /*bad*/copy s, llfty);
+        let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, llfty);
         ccx.monomorphized.insert(hash_id, lldecl);
         lldecl
     };
@@ -227,7 +227,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
                 _
             }, _) => {
         let d = mk_lldecl();
-        set_inline_hint_if_appr(/*bad*/copy i.attrs, d);
+        set_inline_hint_if_appr(i.attrs, d);
         trans_fn(ccx,
                  pt,
                  decl,
@@ -255,8 +255,13 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
         set_inline_hint(d);
         match v.node.kind {
             ast::tuple_variant_kind(ref args) => {
-                trans_enum_variant(ccx, enum_item.id, v, /*bad*/copy *args,
-                                   this_tv.disr_val, Some(psubsts), d);
+                trans_enum_variant(ccx,
+                                   enum_item.id,
+                                   v,
+                                   (*args).clone(),
+                                   this_tv.disr_val,
+                                   Some(psubsts),
+                                   d);
             }
             ast::struct_variant_kind(_) =>
                 ccx.tcx.sess.bug("can't monomorphize struct variants"),
@@ -266,21 +271,21 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
       ast_map::node_method(mth, _, _) => {
         // XXX: What should the self type be here?
         let d = mk_lldecl();
-        set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
+        set_inline_hint_if_appr(mth.attrs.clone(), d);
         meth::trans_method(ccx, pt, mth, Some(psubsts), d);
         d
       }
       ast_map::node_trait_method(@ast::provided(mth), _, pt) => {
         let d = mk_lldecl();
-        set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
-        meth::trans_method(ccx, /*bad*/copy *pt, mth, Some(psubsts), d);
+        set_inline_hint_if_appr(mth.attrs.clone(), d);
+        meth::trans_method(ccx, (*pt).clone(), mth, Some(psubsts), d);
         d
       }
       ast_map::node_struct_ctor(struct_def, _, _) => {
         let d = mk_lldecl();
         set_inline_hint(d);
         base::trans_tuple_struct(ccx,
-                                 /*bad*/copy struct_def.fields,
+                                 struct_def.fields,
                                  struct_def.ctor_id.expect("ast-mapped tuple struct \
                                                             didn't have a ctor id"),
                                  Some(psubsts),
@@ -372,7 +377,7 @@ pub fn make_mono_id(ccx: @mut CrateContext,
       Some(vts) => {
         debug!("make_mono_id vtables=%s substs=%s",
                vts.repr(ccx.tcx), substs.tys.repr(ccx.tcx));
-        let self_vtables = substs.self_vtable.map(|vtbl| @~[copy *vtbl]);
+        let self_vtables = substs.self_vtable.map(|vtbl| @~[(*vtbl).clone()]);
         let vts_iter = self_vtables.iter().chain_(vts.iter());
         vts_iter.zip(substs_iter).transform(|(vtable, subst)| {
             let v = vtable.map(|vt| meth::vtable_id(ccx, vt));
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 2dc3a88fe86..49f9f4481b9 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -92,7 +92,7 @@ impl Reflector {
             *self.visitor_methods).expect(fmt!("Couldn't find visit method \
                                                 for %s", ty_name));
         let mth_ty =
-            ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
+            ty::mk_bare_fn(tcx, self.visitor_methods[mth_idx].fty.clone());
         let v = self.visitor_val;
         debug!("passing %u args:", args.len());
         let mut bcx = self.bcx;
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 67df6f38b3a..9bb7f9571f3 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -25,7 +25,7 @@ use std::cast;
 
 use std::libc::{c_uint};
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct Type {
     priv rf: TypeRef
 }
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index bc11953c073..814ba16fd74 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -83,7 +83,7 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
 
     let cx = Context {
         ccx: ccx,
-        uses: @mut vec::from_elem(n_tps, 0)
+        uses: @mut vec::from_elem(n_tps, 0u)
     };
 
     // If the method is a default method, we mark all of the types as
@@ -99,10 +99,15 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
     }
 
     let map_node = match ccx.tcx.items.find(&fn_id_loc.node) {
-        Some(x) => (/*bad*/copy *x),
-        None    => ccx.sess.bug(fmt!("type_uses_for: unbound item ID %?",
-                                     fn_id_loc))
+        Some(x) => {
+            (*x).clone()
+        }
+        None => {
+            ccx.sess.bug(fmt!("type_uses_for: unbound item ID %?",
+                              fn_id_loc))
+        }
     };
+
     match map_node {
       ast_map::node_item(@ast::item { node: item_fn(_, _, _, _, ref body),
                                       _ }, _) |
@@ -121,11 +126,13 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
       ast_map::node_variant(_, _, _) => {
         for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr;}
       }
-      ast_map::node_foreign_item(i@@foreign_item { node: foreign_item_fn(*),
-                                                   _ },
-                                 abi,
-                                 _,
-                                 _) => {
+      ast_map::node_foreign_item(i@@foreign_item {
+            node: foreign_item_fn(*),
+            _
+        },
+        abi,
+        _,
+        _) => {
         if abi.is_intrinsic() {
             let nm = cx.ccx.sess.str_of(i.ident);
             let name = nm.as_slice();
@@ -161,7 +168,8 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
 
                     "bswap16" | "bswap32" | "bswap64" => 0,
 
-                    // would be cool to make these an enum instead of strings!
+                    // would be cool to make these an enum instead of
+                    // strings!
                     _ => fail!("unknown intrinsic in type_use")
                 }
             };
@@ -169,8 +177,8 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
         }
       }
       ast_map::node_struct_ctor(*) => {
-        // Similarly to node_variant, this monomorphized function just uses
-        // the representations of all of its type parameters.
+        // Similarly to node_variant, this monomorphized function just
+        // uses the representations of all of its type parameters.
         for uint::range(0, n_tps) |n| { cx.uses[n] |= use_repr; }
       }
       _ => {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 35994eb34c7..c02eb271e29 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -96,13 +96,13 @@ impl Method {
     }
 }
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct mt {
     ty: t,
     mutbl: ast::mutability,
 }
 
-#[deriving(Eq, Encodable, Decodable, IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum vstore {
     vstore_fixed(uint),
     vstore_uniq,
@@ -110,7 +110,7 @@ pub enum vstore {
     vstore_slice(Region)
 }
 
-#[deriving(Eq, IterBytes, Encodable, Decodable)]
+#[deriving(Clone, Eq, IterBytes, Encodable, Decodable)]
 pub enum TraitStore {
     BoxTraitStore,              // @Trait
     UniqTraitStore,             // ~Trait
@@ -119,7 +119,7 @@ pub enum TraitStore {
 
 // XXX: This should probably go away at some point. Maybe after destructors
 // do?
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Clone, Eq, Encodable, Decodable)]
 pub enum SelfMode {
     ByCopy,
     ByRef,
@@ -177,8 +177,12 @@ pub enum ast_ty_to_ty_cache_entry {
 
 pub type opt_region_variance = Option<region_variance>;
 
-#[deriving(Eq, Decodable, Encodable)]
-pub enum region_variance { rv_covariant, rv_invariant, rv_contravariant }
+#[deriving(Clone, Eq, Decodable, Encodable)]
+pub enum region_variance {
+    rv_covariant,
+    rv_invariant,
+    rv_contravariant,
+}
 
 #[deriving(Decodable, Encodable)]
 pub enum AutoAdjustment {
@@ -366,14 +370,14 @@ pub fn type_has_regions(t: t) -> bool {
 }
 pub fn type_id(t: t) -> uint { get(t).id }
 
-#[deriving(Eq,IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct BareFnTy {
     purity: ast::purity,
     abis: AbiSet,
     sig: FnSig
 }
 
-#[deriving(Eq,IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct ClosureTy {
     purity: ast::purity,
     sigil: ast::Sigil,
@@ -390,21 +394,21 @@ pub struct ClosureTy {
  * - `lifetimes` is the list of region names bound in this fn.
  * - `inputs` is the list of arguments and their modes.
  * - `output` is the return type. */
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct FnSig {
     bound_lifetime_names: OptVec<ast::ident>,
     inputs: ~[t],
     output: t
 }
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct param_ty {
     idx: uint,
     def_id: def_id
 }
 
 /// Representation of regions:
-#[deriving(Eq, IterBytes, Encodable, Decodable)]
+#[deriving(Clone, Eq, IterBytes, Encodable, Decodable)]
 pub enum Region {
     /// Bound regions are found (primarily) in function types.  They indicate
     /// region parameters that have yet to be replaced with actual regions
@@ -450,13 +454,13 @@ impl Region {
     }
 }
 
-#[deriving(Eq, IterBytes, Encodable, Decodable)]
+#[deriving(Clone, Eq, IterBytes, Encodable, Decodable)]
 pub struct FreeRegion {
     scope_id: node_id,
     bound_region: bound_region
 }
 
-#[deriving(Eq, IterBytes, Encodable, Decodable)]
+#[deriving(Clone, Eq, IterBytes, Encodable, Decodable)]
 pub enum bound_region {
     /// The self region for structs, impls (&T in a type defn or &'self T)
     br_self,
@@ -501,7 +505,7 @@ type opt_region = Option<Region>;
  * - `self_ty` is the type to which `self` should be remapped, if any.  The
  *   `self` type is rather funny in that it can only appear on traits and is
  *   always substituted away to the implementing type for a trait. */
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct substs {
     self_r: opt_region,
     self_ty: Option<ty::t>,
@@ -557,7 +561,7 @@ mod primitives {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // AST structure in libsyntax/ast.rs as well.
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub enum sty {
     ty_nil,
     ty_bot,
@@ -600,22 +604,25 @@ pub struct TraitRef {
     substs: substs
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum IntVarValue {
     IntType(ast::int_ty),
     UintType(ast::uint_ty),
 }
 
+#[deriving(Clone)]
 pub enum terr_vstore_kind {
     terr_vec, terr_str, terr_fn, terr_trait
 }
 
+#[deriving(Clone)]
 pub struct expected_found<T> {
     expected: T,
     found: T
 }
 
 // Data structures used in type unification
+#[deriving(Clone)]
 pub enum type_err {
     terr_mismatch,
     terr_purity_mismatch(expected_found<purity>),
@@ -657,7 +664,7 @@ pub struct ParamBounds {
 
 pub type BuiltinBounds = EnumSet<BuiltinBound>;
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub enum BuiltinBound {
     BoundCopy,
     BoundStatic,
@@ -689,28 +696,28 @@ impl CLike for BuiltinBound {
     }
 }
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct TyVid(uint);
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct IntVid(uint);
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct FloatVid(uint);
 
-#[deriving(Eq, Encodable, Decodable, IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct RegionVid {
     id: uint
 }
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub enum InferTy {
     TyVar(TyVid),
     IntVar(IntVid),
     FloatVar(FloatVid)
 }
 
-#[deriving(Encodable, Decodable, IterBytes)]
+#[deriving(Clone, Encodable, Decodable, IterBytes)]
 pub enum InferRegion {
     ReVar(RegionVid),
     ReSkolemized(uint, bound_region)
@@ -795,6 +802,7 @@ impl ToStr for IntVarValue {
     }
 }
 
+#[deriving(Clone)]
 pub struct TypeParameterDef {
     ident: ast::ident,
     def_id: ast::def_id,
@@ -803,6 +811,7 @@ pub struct TypeParameterDef {
 
 /// Information about the type/lifetime parametesr associated with an item.
 /// Analogous to ast::Generics.
+#[deriving(Clone)]
 pub struct Generics {
     type_param_defs: @~[TypeParameterDef],
     region_param: Option<region_variance>,
@@ -824,6 +833,7 @@ impl Generics {
 ///
 /// - `ty`: the base type.  May have reference to the (unsubstituted) bound
 ///   region `&self` or to (unsubstituted) ty_param types
+#[deriving(Clone)]
 pub struct ty_param_bounds_and_ty {
     generics: Generics,
     ty: t
@@ -1264,7 +1274,7 @@ pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
     let args = sig.inputs.map(|arg| fldop(*arg));
 
     FnSig {
-        bound_lifetime_names: copy sig.bound_lifetime_names,
+        bound_lifetime_names: sig.bound_lifetime_names.clone(),
         inputs: args,
         output: fldop(sig.output)
     }
@@ -1314,7 +1324,14 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
         }
         ty_closure(ref f) => {
             let sig = fold_sig(&f.sig, fldop);
-            ty_closure(ClosureTy {sig: sig, ..copy *f})
+            ty_closure(ClosureTy {
+                sig: sig,
+                purity: f.purity,
+                sigil: f.sigil,
+                onceness: f.onceness,
+                region: f.region,
+                bounds: f.bounds,
+            })
         }
         ty_rptr(r, ref tm) => {
             ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
@@ -1325,7 +1342,7 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
         ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
         ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
         ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self(_) => {
-            /*bad*/copy *sty
+            (*sty).clone()
         }
     }
 }
@@ -1400,13 +1417,21 @@ pub fn fold_regions_and_ty(
         ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl, bounds)
       }
       ty_bare_fn(ref f) => {
-          ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt),
-                                       ..copy *f})
+          ty::mk_bare_fn(cx, BareFnTy {
+            sig: fold_sig(&f.sig, fldfnt),
+            purity: f.purity,
+            abis: f.abis.clone(),
+          })
       }
       ty_closure(ref f) => {
-          ty::mk_closure(cx, ClosureTy {region: fldr(f.region),
-                                        sig: fold_sig(&f.sig, fldfnt),
-                                        ..copy *f})
+          ty::mk_closure(cx, ClosureTy {
+            region: fldr(f.region),
+            sig: fold_sig(&f.sig, fldfnt),
+            purity: f.purity,
+            sigil: f.sigil,
+            onceness: f.onceness,
+            bounds: f.bounds,
+          })
       }
       ref sty => {
         fold_sty_to_ty(cx, sty, |t| fldt(t))
@@ -2493,9 +2518,11 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
       ty_enum(did, ref substs) => {
         let variants = enum_variants(cx, did);
         for (*variants).iter().advance |variant| {
-            let tup_ty = mk_tup(cx, /*bad*/copy variant.args);
-
+            // XXX(pcwalton): This is an inefficient way to do this. Don't
+            // synthesize a tuple!
+            //
             // Perform any type parameter substitutions.
+            let tup_ty = mk_tup(cx, variant.args.clone());
             let tup_ty = subst(cx, substs, tup_ty);
             if !type_is_pod(cx, tup_ty) { result = false; }
         }
@@ -2711,10 +2738,11 @@ pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
     }
 }
 
+// XXX(pcwalton): Makes a copy, bleh. Probably better to not do that.
 pub fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
     match cx.node_type_substs.find(&id) {
       None => return ~[],
-      Some(ts) => return /*bad*/ copy *ts
+      Some(ts) => return (*ts).clone(),
     }
 }
 
@@ -2724,8 +2752,8 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
 
 pub fn ty_fn_sig(fty: t) -> FnSig {
     match get(fty).sty {
-        ty_bare_fn(ref f) => copy f.sig,
-        ty_closure(ref f) => copy f.sig,
+        ty_bare_fn(ref f) => f.sig.clone(),
+        ty_closure(ref f) => f.sig.clone(),
         ref s => {
             fail!("ty_fn_sig() called on non-fn type: %?", s)
         }
@@ -2735,8 +2763,8 @@ pub fn ty_fn_sig(fty: t) -> FnSig {
 // Type accessors for substructures of types
 pub fn ty_fn_args(fty: t) -> ~[t] {
     match get(fty).sty {
-        ty_bare_fn(ref f) => copy f.sig.inputs,
-        ty_closure(ref f) => copy f.sig.inputs,
+        ty_bare_fn(ref f) => f.sig.inputs.clone(),
+        ty_closure(ref f) => f.sig.inputs.clone(),
         ref s => {
             fail!("ty_fn_args() called on non-fn type: %?", s)
         }
@@ -2823,8 +2851,8 @@ pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
     match ty::get(fn_type).sty {
         ty::ty_closure(ref fty) => {
             ty::mk_closure(tcx, ClosureTy {
-                sig: FnSig {output: ret_type, ..copy fty.sig},
-                ..copy *fty
+                sig: FnSig {output: ret_type, ..fty.sig.clone()},
+                ..(*fty).clone()
             })
         }
         _ => {
@@ -2906,7 +2934,7 @@ pub fn adjust_ty(cx: ctxt,
                                        onceness: ast::Many,
                                        region: r,
                                        bounds: ty::AllBuiltinBounds(),
-                                       sig: copy b.sig})
+                                       sig: b.sig.clone()})
                 }
                 ref b => {
                     cx.sess.bug(
@@ -2990,7 +3018,7 @@ pub fn adjust_ty(cx: ctxt,
                 ty::mk_closure(cx, ClosureTy {
                     sigil: BorrowedSigil,
                     region: r,
-                    ..copy *fty
+                    ..(*fty).clone()
                 })
             }
 
@@ -3034,11 +3062,10 @@ pub fn expr_has_ty_params(cx: ctxt, expr: &ast::expr) -> bool {
     return node_id_has_type_params(cx, expr.id);
 }
 
-pub fn method_call_type_param_defs(
-    tcx: ctxt,
-    method_map: typeck::method_map,
-    id: ast::node_id) -> Option<@~[TypeParameterDef]>
-{
+pub fn method_call_type_param_defs(tcx: ctxt,
+                                   method_map: typeck::method_map,
+                                   id: ast::node_id)
+                                   -> Option<@~[TypeParameterDef]> {
     do method_map.find(&id).map |method| {
         match method.origin {
           typeck::method_static(did) => {
@@ -3059,8 +3086,10 @@ pub fn method_call_type_param_defs(
             let trait_type_param_defs =
                 ty::lookup_trait_def(tcx, trt_id).generics.type_param_defs;
             @vec::append(
-                copy *trait_type_param_defs,
-                *ty::trait_method(tcx, trt_id, n_mth).generics.type_param_defs)
+                (*trait_type_param_defs).clone(),
+                *ty::trait_method(tcx,
+                                  trt_id,
+                                  n_mth).generics.type_param_defs)
           }
         }
     }
@@ -3548,7 +3577,7 @@ pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef]
         |supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs))
 }
 
-fn lookup_locally_or_in_crate_store<V:Copy>(
+fn lookup_locally_or_in_crate_store<V:Clone>(
     descr: &str,
     def_id: ast::def_id,
     map: &mut HashMap<ast::def_id, V>,
@@ -3566,7 +3595,7 @@ fn lookup_locally_or_in_crate_store<V:Copy>(
      */
 
     match map.find(&def_id) {
-        Some(&ref v) => { return copy *v; }
+        Some(&ref v) => { return (*v).clone(); }
         None => { }
     }
 
@@ -3574,8 +3603,8 @@ fn lookup_locally_or_in_crate_store<V:Copy>(
         fail!("No def'n found for %? in tcx.%s", def_id, descr);
     }
     let v = load_external();
-    map.insert(def_id, copy v);
-    return copy v;
+    map.insert(def_id, v.clone());
+    v
 }
 
 pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method {
@@ -3679,6 +3708,7 @@ fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option<ast::def_id> {
 }
 
 // Enum information
+#[deriving(Clone)]
 pub struct VariantInfo_ {
     args: ~[t],
     ctor_ty: t,
@@ -3700,8 +3730,11 @@ pub fn substd_enum_variants(cx: ctxt,
 
         let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
 
-        @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
-                      ../*bad*/copy **variant_info}
+        @VariantInfo_ {
+            args: substd_args,
+            ctor_ty: substd_ctor_ty,
+            ..(**variant_info).clone()
+        }
     }.collect()
 }
 
@@ -3770,21 +3803,21 @@ pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
                 ast_map::path_name(item.ident)
               }
             };
-            vec::append_one(/*bad*/copy *path, item_elt)
+            vec::append_one((*path).clone(), item_elt)
           }
 
           ast_map::node_foreign_item(nitem, _, _, path) => {
-            vec::append_one(/*bad*/copy *path,
+            vec::append_one((*path).clone(),
                             ast_map::path_name(nitem.ident))
           }
 
           ast_map::node_method(method, _, path) => {
-            vec::append_one(/*bad*/copy *path,
+            vec::append_one((*path).clone(),
                             ast_map::path_name(method.ident))
           }
           ast_map::node_trait_method(trait_method, _, path) => {
             let method = ast_util::trait_method_to_ty_method(&*trait_method);
-            vec::append_one(/*bad*/copy *path,
+            vec::append_one((*path).clone(),
                             ast_map::path_name(method.ident))
           }
 
@@ -3794,7 +3827,7 @@ pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
           }
 
           ast_map::node_struct_ctor(_, item, path) => {
-            vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident))
+            vec::append_one((*path).clone(), ast_map::path_name(item.ident))
           }
 
           ref node => {
@@ -4193,7 +4226,7 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
         ty_closure(ref closure_ty) => {
             mk_closure(cx, ClosureTy {
                 region: ty::re_static,
-                ..copy *closure_ty
+                ..(*closure_ty).clone()
             })
         }
 
@@ -4205,7 +4238,7 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
                      substs {
                         self_r: Some(ty::re_static),
                         self_ty: None,
-                        tps: /*bad*/copy (*r).tps
+                        tps: (*r).tps.clone()
                      }),
                 None =>
                     t
@@ -4217,7 +4250,7 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
                 // Ditto.
                 mk_struct(cx, did, substs {self_r: Some(ty::re_static),
                                            self_ty: None,
-                                           tps: /*bad*/copy (*r).tps}),
+                                           tps: (*r).tps.clone()}),
               None =>
                 t
             },
@@ -4403,6 +4436,10 @@ pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> {
     let mut static_trait_bound = EmptyBuiltinBounds();
     static_trait_bound.add(BoundStatic);
     Ok((trait_ref,
-        mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs,
-                 BoxTraitStore, ast::m_imm, static_trait_bound)))
+        mk_trait(tcx,
+                 trait_ref.def_id,
+                 trait_ref.substs.clone(),
+                 BoxTraitStore,
+                 ast::m_imm,
+                 static_trait_bound)))
 }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index e9297b12ed0..343cbc2bea7 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -105,7 +105,7 @@ pub fn get_region_reporting_err(
     }
 }
 
-pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + 'static>(
+pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     default_span: span,
@@ -130,7 +130,7 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + 'static>(
     get_region_reporting_err(this.tcx(), span, opt_lifetime, res)
 }
 
-fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + 'static>(
+fn ast_path_substs<AC:AstConv,RS:region_scope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     def_id: ast::def_id,
@@ -184,12 +184,13 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + 'static>(
     substs {self_r:self_r, self_ty:self_ty, tps:tps}
 }
 
-pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
-    this: &AC,
-    rscope: &RS,
-    did: ast::def_id,
-    path: &ast::Path) -> ty_param_substs_and_ty
-{
+pub fn ast_path_to_substs_and_ty<AC:AstConv,
+                                 RS:region_scope + Clone + 'static>(
+                                 this: &AC,
+                                 rscope: &RS,
+                                 did: ast::def_id,
+                                 path: &ast::Path)
+                                 -> ty_param_substs_and_ty {
     let tcx = this.tcx();
     let ty::ty_param_bounds_and_ty {
         generics: generics,
@@ -201,7 +202,7 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
     ty_param_substs_and_ty { substs: substs, ty: ty }
 }
 
-pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Copy + 'static>(
+pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     trait_def_id: ast::def_id,
@@ -224,7 +225,7 @@ pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Copy + 'static>(
     return trait_ref;
 }
 
-pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
+pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Clone + 'static>(
         this: &AC,
         rscope: &RS,
         did: ast::def_id,
@@ -246,10 +247,10 @@ pub static NO_TPS: uint = 2;
 // Parses the programmer's textual representation of a type into our
 // internal notion of a type. `getter` is a function that returns the type
 // corresponding to a definition ID:
-pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
+pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Clone + 'static>(
     this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
 
-    fn ast_mt_to_mt<AC:AstConv, RS:region_scope + Copy + 'static>(
+    fn ast_mt_to_mt<AC:AstConv, RS:region_scope + Clone + 'static>(
         this: &AC, rscope: &RS, mt: &ast::mt) -> ty::mt {
 
         ty::mt {ty: ast_ty_to_ty(this, rscope, mt.ty), mutbl: mt.mutbl}
@@ -258,7 +259,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
     // Handle @, ~, and & being able to mean estrs and evecs.
     // If a_seq_ty is a str or a vec, make it an estr/evec.
     // Also handle first-class trait types.
-    fn mk_pointer<AC:AstConv,RS:region_scope + Copy + 'static>(
+    fn mk_pointer<AC:AstConv,RS:region_scope + Clone + 'static>(
         this: &AC,
         rscope: &RS,
         a_seq_ty: &ast::mt,
@@ -305,7 +306,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
                         let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
                         return ty::mk_trait(tcx,
                                             result.def_id,
-                                            copy result.substs,
+                                            result.substs.clone(),
                                             trait_store,
                                             a_seq_ty.mutbl,
                                             bounds);
@@ -522,7 +523,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
 }
 
 pub fn ty_of_arg<AC:AstConv,
-                 RS:region_scope + Copy + 'static>(
+                 RS:region_scope + Clone + 'static>(
                  this: &AC,
                  rscope: &RS,
                  a: &ast::arg,
@@ -570,7 +571,7 @@ struct SelfInfo {
     explicit_self: ast::explicit_self
 }
 
-pub fn ty_of_method<AC:AstConv,RS:region_scope + Copy + 'static>(
+pub fn ty_of_method<AC:AstConv,RS:region_scope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     purity: ast::purity,
@@ -588,7 +589,7 @@ pub fn ty_of_method<AC:AstConv,RS:region_scope + Copy + 'static>(
     (a.get(), b)
 }
 
-pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
+pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     purity: ast::purity,
@@ -601,7 +602,7 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
     b
 }
 
-fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
+fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     purity: ast::purity,
@@ -615,7 +616,9 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
     // new region names that appear inside of the fn decl are bound to
     // that function type
     let bound_lifetime_names = bound_lifetimes(this, lifetimes);
-    let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names));
+    let rb =
+        in_binding_rscope(rscope,
+                          RegionParamNames(bound_lifetime_names.clone()));
 
     let opt_transformed_self_ty = opt_self_info.map(|&self_info| {
         transform_self_ty(this, &rb, self_info)
@@ -637,7 +640,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
                                 output: output_ty}
             });
 
-    fn transform_self_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
+    fn transform_self_ty<AC:AstConv,RS:region_scope + Clone + 'static>(
         this: &AC,
         rscope: &RS,
         self_info: &SelfInfo) -> Option<ty::t>
@@ -670,7 +673,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
     }
 }
 
-pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
+pub fn ty_of_closure<AC:AstConv,RS:region_scope + Clone + 'static>(
     this: &AC,
     rscope: &RS,
     sigil: ast::Sigil,
@@ -716,7 +719,9 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
     // new region names that appear inside of the fn decl are bound to
     // that function type
     let bound_lifetime_names = bound_lifetimes(this, lifetimes);
-    let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names));
+    let rb =
+        in_binding_rscope(rscope,
+                          RegionParamNames(bound_lifetime_names.clone()));
 
     let input_tys = do decl.inputs.iter().enumerate().transform |(i, a)| {
         let expected_arg_ty = do expected_sig.chain_ref |e| {
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 5f0a32bb02e..c16e9a0a928 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -120,7 +120,7 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: &ast::Path,
     // contains type variables.
 
     // Check to see whether this is an enum or a struct.
-    match structure_of(pcx.fcx, pat.span, expected) {
+    match *structure_of(pcx.fcx, pat.span, expected) {
         ty::ty_enum(_, ref expected_substs) => {
             // Lookup the enum and variant def ids:
             let v_def = lookup_def(pcx.fcx, pat.span, pat.id);
@@ -165,8 +165,9 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: &ast::Path,
                              None);
                     fcx.write_error(pat.id);
                     kind_name = "[error]";
-                    arg_types = (copy *subpats).get_or_default(~[]).map(|_|
-                                                                        ty::mk_err());
+                    arg_types = (*subpats).clone()
+                                          .get_or_default(~[])
+                                          .map(|_| ty::mk_err());
                 }
             }
         }
@@ -207,8 +208,9 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: &ast::Path,
                     None);
             fcx.write_error(pat.id);
             kind_name = "[error]";
-            arg_types = (copy *subpats).get_or_default(~[]).map(|_|
-                                                                ty::mk_err());
+            arg_types = (*subpats).clone()
+                                  .get_or_default(~[])
+                                  .map(|_| ty::mk_err());
         }
     }
 
@@ -486,7 +488,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
         // Grab the class data that we care about.
         let structure = structure_of(fcx, pat.span, expected);
         let mut error_happened = false;
-        match structure {
+        match *structure {
             ty::ty_struct(cid, ref substs) => {
                 check_struct_pat(pcx, pat.id, pat.span, expected, path,
                                  *fields, etc, cid, substs);
@@ -507,15 +509,14 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
         // Finally, write in the type.
         if error_happened {
             fcx.write_error(pat.id);
-        }
-        else {
+        } else {
             fcx.write_ty(pat.id, expected);
         }
       }
       ast::pat_tup(ref elts) => {
         let s = structure_of(fcx, pat.span, expected);
         let e_count = elts.len();
-        match s {
+        match *s {
             ty::ty_tup(ref ex_elts) if e_count == ex_elts.len() => {
                 for elts.iter().enumerate().advance |(i, elt)| {
                     check_pat(pcx, *elt, ex_elts[i]);
@@ -527,7 +528,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
                     check_pat(pcx, *elt, ty::mk_err());
                 }
                 // use terr_tuple_size if both types are tuples
-                let type_error = match s {
+                let type_error = match *s {
                     ty::ty_tup(ref ex_elts) =>
                         ty::terr_tuple_size(ty::expected_found{expected: ex_elts.len(),
                                                            found: e_count}),
@@ -555,9 +556,9 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
             fcx.infcx().next_region_var(
                 infer::PatternRegion(pat.span));
 
-        let (elt_type, region_var) = match structure_of(
-          fcx, pat.span, expected
-        ) {
+        let (elt_type, region_var) = match *structure_of(fcx,
+                                                         pat.span,
+                                                         expected) {
           ty::ty_evec(mt, vstore) => {
             let region_var = match vstore {
                 ty::vstore_slice(r) => r,
@@ -626,7 +627,7 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
         check_pat(pcx, inner, e_inner.ty);
         fcx.write_ty(pat_id, expected);
     };
-    match structure_of(fcx, span, expected) {
+    match *structure_of(fcx, span, expected) {
         ty::ty_box(e_inner) if pointer_kind == Managed => {
             check_inner(e_inner);
         }
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 04c83f40f6c..d2a11953af0 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -171,6 +171,7 @@ pub struct LookupContext<'self> {
  * A potential method that might be called, assuming the receiver
  * is of a suitable type.
  */
+#[deriving(Clone)]
 pub struct Candidate {
     rcvr_ty: ty::t,
     rcvr_substs: ty::substs,
@@ -384,7 +385,7 @@ impl<'self> LookupContext<'self> {
 
             let cand = Candidate {
                 rcvr_ty: rcvr_ty,
-                rcvr_substs: copy bound_trait_ref.substs,
+                rcvr_substs: bound_trait_ref.substs.clone(),
                 method_ty: method,
                 origin: method_param(
                     method_param {
@@ -441,7 +442,7 @@ impl<'self> LookupContext<'self> {
         // for Self.
         let rcvr_substs = substs {
             self_ty: Some(self_ty),
-            ../*bad*/copy *substs
+            ..(*substs).clone()
         };
 
         self.inherent_candidates.push(Candidate {
@@ -506,7 +507,7 @@ impl<'self> LookupContext<'self> {
                 };
                 self.inherent_candidates.push(Candidate {
                     rcvr_ty: self_ty,
-                    rcvr_substs: copy info.trait_ref.substs,
+                    rcvr_substs: info.trait_ref.substs.clone(),
                     method_ty: info.method_ty,
                     origin: origin
                 });
@@ -814,8 +815,9 @@ impl<'self> LookupContext<'self> {
                                rcvr_ty: ty::t,
                                candidates: &mut ~[Candidate])
                                -> Option<method_map_entry> {
+        // XXX(pcwalton): Do we need to clone here?
         let relevant_candidates: ~[Candidate] =
-            candidates.iter().transform(|c| copy *c).
+            candidates.iter().transform(|c| (*c).clone()).
                 filter(|c| self.is_relevant(rcvr_ty, c)).collect();
 
         let relevant_candidates = self.merge_candidates(relevant_candidates);
@@ -840,7 +842,7 @@ impl<'self> LookupContext<'self> {
         let mut merged = ~[];
         let mut i = 0;
         while i < candidates.len() {
-            let candidate_a = /*bad*/copy candidates[i];
+            let candidate_a = &candidates[i];
 
             let mut skip = false;
 
@@ -875,7 +877,7 @@ impl<'self> LookupContext<'self> {
                 // There are more than one of these and we need only one
                 loop;
             } else {
-                merged.push(candidate_a);
+                merged.push(candidate_a.clone());
             }
         }
 
@@ -951,9 +953,9 @@ impl<'self> LookupContext<'self> {
         // Construct the full set of type parameters for the method,
         // which is equal to the class tps + the method tps.
         let all_substs = substs {
-            tps: vec::append(/*bad*/copy candidate.rcvr_substs.tps,
-                             m_substs),
-            ../*bad*/copy candidate.rcvr_substs
+            tps: vec::append(candidate.rcvr_substs.tps.clone(), m_substs),
+            self_r: candidate.rcvr_substs.self_r,
+            self_ty: candidate.rcvr_substs.self_ty,
         };
 
         // Compute the method type with type parameters substituted
@@ -966,7 +968,7 @@ impl<'self> LookupContext<'self> {
         // Replace any bound regions that appear in the function
         // signature with region variables
         let bare_fn_ty = match ty::get(fty).sty {
-            ty::ty_bare_fn(ref f) => copy *f,
+            ty::ty_bare_fn(ref f) => f,
             ref s => {
                 tcx.sess.span_bug(
                     self.expr.span,
@@ -979,7 +981,11 @@ impl<'self> LookupContext<'self> {
                 |br| self.fcx.infcx().next_region_var(
                     infer::BoundRegionInFnCall(self.expr.span, br)));
         let transformed_self_ty = opt_transformed_self_ty.get();
-        let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty});
+        let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
+            sig: fn_sig,
+            purity: bare_fn_ty.purity,
+            abis: bare_fn_ty.abis.clone(),
+        });
         debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty));
 
         let self_mode = get_mode_from_explicit_self(candidate.method_ty.explicit_self);
@@ -1178,7 +1184,7 @@ impl<'self> LookupContext<'self> {
                                 trait_did: def_id,
                                 method_num: uint) -> ty::t {
             let trait_methods = ty::trait_methods(tcx, trait_did);
-            ty::mk_bare_fn(tcx, copy trait_methods[method_num].fty)
+            ty::mk_bare_fn(tcx, trait_methods[method_num].fty.clone())
         }
     }
 
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 365d4e1cf94..deec93140b4 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -168,6 +168,7 @@ pub struct inherited {
     vtable_map: vtable_map,
 }
 
+#[deriving(Clone)]
 pub enum FnKind {
     // This is a for-closure.  The ty::t is the return type of the
     // enclosing function.
@@ -180,6 +181,7 @@ pub enum FnKind {
     Vanilla
 }
 
+#[deriving(Clone)]
 pub struct PurityState {
     def: ast::node_id,
     purity: ast::purity,
@@ -219,6 +221,7 @@ enum AllowOverloadedOperatorsFlag {
     DontAllowOverloadedOperators,
 }
 
+#[deriving(Clone)]
 pub struct FnCtxt {
     // Number of errors that had been reported when we started
     // checking this function. On exit, if we find that *more* errors
@@ -833,7 +836,7 @@ impl FnCtxt {
 
     pub fn node_ty_substs(&self, id: ast::node_id) -> ty::substs {
         match self.inh.node_type_substs.find(&id) {
-            Some(ts) => (/*bad*/copy *ts),
+            Some(ts) => (*ts).clone(),
             None => {
                 self.tcx().sess.bug(
                     fmt!("no type substs for node %d: %s in fcx %s",
@@ -986,7 +989,7 @@ pub fn do_autoderef(fcx: @mut FnCtxt, sp: span, t: ty::t) -> (ty::t, uint) {
         let sty = structure_of(fcx, sp, t1);
 
         // Some extra checks to detect weird cycles and so forth:
-        match sty {
+        match *sty {
             ty::ty_box(inner) | ty::ty_uniq(inner) |
             ty::ty_rptr(_, inner) => {
                 match ty::get(t1).sty {
@@ -1014,7 +1017,7 @@ pub fn do_autoderef(fcx: @mut FnCtxt, sp: span, t: ty::t) -> (ty::t, uint) {
         }
 
         // Otherwise, deref if type is derefable:
-        match ty::deref_sty(fcx.ccx.tcx, &sty, false) {
+        match ty::deref_sty(fcx.ccx.tcx, sty, false) {
             None => {
                 return (t1, autoderefs);
             }
@@ -1352,28 +1355,35 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         // Extract the function signature from `in_fty`.
         let fn_sty = structure_of(fcx, f.span, fn_ty);
 
-        let fn_sig = match fn_sty {
-            ty::ty_bare_fn(ty::BareFnTy {sig: sig, _}) |
-            ty::ty_closure(ty::ClosureTy {sig: sig, _}) => sig,
+        // This is the "default" function signature, used in case of error.
+        // In that case, we check each argument against "error" in order to
+        // set up all the node type bindings.
+        let error_fn_sig = FnSig {
+            bound_lifetime_names: opt_vec::Empty,
+            inputs: err_args(args.len()),
+            output: ty::mk_err()
+        };
+
+        let fn_sig = match *fn_sty {
+            ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
+            ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => sig,
             _ => {
                 fcx.type_error_message(call_expr.span, |actual| {
                     fmt!("expected function but \
                           found `%s`", actual) }, fn_ty, None);
-
-                // check each arg against "error", in order to set up
-                // all the node type bindings
-                FnSig {bound_lifetime_names: opt_vec::Empty,
-                       inputs: err_args(args.len()),
-                       output: ty::mk_err()}
+                &error_fn_sig
             }
         };
 
         // Replace any bound regions that appear in the function
         // signature with region variables
         let (_, _, fn_sig) =
-            replace_bound_regions_in_fn_sig(
-                fcx.tcx(), @Nil, None, &fn_sig,
-                |br| fcx.infcx().next_region_var(
+            replace_bound_regions_in_fn_sig(fcx.tcx(),
+                                            @Nil,
+                                            None,
+                                            fn_sig,
+                                            |br| fcx.infcx()
+                                                    .next_region_var(
                     infer::BoundRegionInFnCall(call_expr.span, br)));
 
         // Call the generic checker.
@@ -1708,7 +1718,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         // to impure and block. Note that we only will use those for
         // block syntax lambdas; that is, lambdas without explicit
         // sigils.
-        let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
+        let expected_sty = unpack_expected(fcx,
+                                           expected,
+                                           |x| Some((*x).clone()));
         let error_happened = false;
         let (expected_sig,
              expected_purity,
@@ -1761,10 +1773,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                 output: ty::mk_err()
             };
             ty::mk_err()
-        }
-        else {
-            let fn_ty_copy = copy fn_ty;
-            fty_sig = copy fn_ty.sig;
+        } else {
+            let fn_ty_copy = fn_ty.clone();
+            fty_sig = fn_ty.sig.clone();
             ty::mk_closure(tcx, fn_ty_copy)
         };
 
@@ -1795,7 +1806,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                                                 fcx.expr_ty(base));
         let (base_t, derefs) = do_autoderef(fcx, expr.span, expr_t);
 
-        match structure_of(fcx, expr.span, base_t) {
+        match *structure_of(fcx, expr.span, base_t) {
             ty::ty_struct(base_id, ref substs) => {
                 // This is just for fields -- the same code handles
                 // methods in both classes and traits
@@ -2119,16 +2130,20 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         // 2. the closure that was given returns unit
         let tcx = fcx.tcx();
         let mut err_happened = false;
-        let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
+        let expected_sty = unpack_expected(fcx,
+                                           expected,
+                                           |x| Some((*x).clone()));
         let inner_ty = match expected_sty {
             Some(ty::ty_closure(ref fty)) => {
                 match fcx.mk_subty(false, infer::Misc(expr.span),
                                    fty.sig.output, ty::mk_bool()) {
                     result::Ok(_) => {
                         ty::mk_closure(tcx, ty::ClosureTy {
-                            sig: FnSig {output: ty::mk_nil(),
-                                        ..copy fty.sig},
-                            ..copy *fty
+                            sig: FnSig {
+                                output: ty::mk_nil(),
+                                ..fty.sig.clone()
+                            },
+                            ..(*fty).clone()
                         })
                     }
                     result::Err(_) => {
@@ -2361,13 +2376,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                 }
                 ast::deref => {
                     let sty = structure_of(fcx, expr.span, oprnd_t);
-                    let operand_ty = ty::deref_sty(tcx, &sty, true);
+                    let operand_ty = ty::deref_sty(tcx, sty, true);
                     match operand_ty {
                         Some(mt) => {
                             oprnd_t = mt.ty
                         }
                         None => {
-                            match sty {
+                            match *sty {
                                 ty::ty_enum(*) => {
                                     tcx.sess.span_err(
                                         expr.span,
@@ -2564,7 +2579,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
           check_loop_body(fcx, expr, expected, loop_body);
       }
       ast::expr_do_body(b) => {
-        let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
+        let expected_sty = unpack_expected(fcx,
+                                           expected,
+                                           |x| Some((*x).clone()));
         let inner_ty = match expected_sty {
             Some(ty::ty_closure(_)) => expected.get(),
             _ => match expected {
@@ -2759,7 +2776,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
       }
       ast::expr_tup(ref elts) => {
         let flds = unpack_expected(fcx, expected, |sty| {
-            match *sty { ty::ty_tup(ref flds) => Some(copy *flds), _ => None }
+            match *sty {
+                ty::ty_tup(ref flds) => Some((*flds).clone()),
+                _ => None
+            }
         });
         let mut bot_field = false;
         let mut err_field = false;
@@ -2816,7 +2836,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
           } else {
               let (base_t, derefs) = do_autoderef(fcx, expr.span, raw_base_t);
               let base_sty = structure_of(fcx, expr.span, base_t);
-              match ty::index_sty(&base_sty) {
+              match ty::index_sty(base_sty) {
                   Some(mt) => {
                       require_integral(fcx, idx.span, idx_t);
                       fcx.write_ty(id, mt.ty);
@@ -3374,8 +3394,9 @@ pub fn structurally_resolved_type(fcx: @mut FnCtxt, sp: span, tp: ty::t)
 }
 
 // Returns the one-level-deep structure of the given type.
-pub fn structure_of(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> ty::sty {
-    /*bad*/copy ty::get(structurally_resolved_type(fcx, sp, typ)).sty
+pub fn structure_of<'a>(fcx: @mut FnCtxt, sp: span, typ: ty::t)
+                        -> &'a ty::sty {
+    &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
 }
 
 pub fn type_is_integral(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 7cc32867414..d9036c72db6 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -132,9 +132,12 @@ fn lookup_vtables(vcx: &VtableContext,
     @result
 }
 
-fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
-                id: ast::def_id, substs: ty::substs,
-                is_early: bool) -> Option<ty::substs> {
+fn fixup_substs(vcx: &VtableContext,
+                location_info: &LocationInfo,
+                id: ast::def_id,
+                substs: ty::substs,
+                is_early: bool)
+                -> Option<ty::substs> {
     let tcx = vcx.tcx();
     // use a dummy type just to package up the substs that need fixing up
     let t = ty::mk_trait(tcx,
@@ -144,7 +147,7 @@ fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
                          ty::EmptyBuiltinBounds());
     do fixup_ty(vcx, location_info, t, is_early).map |t_f| {
         match ty::get(*t_f).sty {
-          ty::ty_trait(_, ref substs_f, _, _, _) => (/*bad*/copy *substs_f),
+          ty::ty_trait(_, ref substs_f, _, _, _) => (*substs_f).clone(),
           _ => fail!("t_f should be a trait")
         }
     }
@@ -365,7 +368,7 @@ fn lookup_vtable(vcx: &VtableContext,
                                                               trait_ref.def_id,
                                                               substs,
                                                               is_early) {
-                                Some(ref substs) => (/*bad*/copy *substs),
+                                Some(ref substs) => (*substs).clone(),
                                 None => {
                                     assert!(is_early);
                                     // Bail out with a bogus answer
@@ -403,10 +406,9 @@ fn lookup_vtable(vcx: &VtableContext,
                             // the impl as well as the resolved list
                             // of type substitutions for the target
                             // trait.
-                            found.push(
-                                vtable_static(im.did,
-                                              /*bad*/copy substs_f.tps,
-                                              subres));
+                            found.push(vtable_static(im.did,
+                                                     substs_f.tps.clone(),
+                                                     subres));
                         }
                     }
                 }
@@ -414,14 +416,14 @@ fn lookup_vtable(vcx: &VtableContext,
 
             match found.len() {
                 0 => { /* fallthrough */ }
-                1 => { return Some(/*bad*/copy found[0]); }
+                1 => return Some(found[0].clone()),
                 _ => {
                     if !is_early {
                         vcx.tcx().sess.span_err(
                             location_info.span,
                             "multiple applicable methods in scope");
                     }
-                    return Some(/*bad*/copy found[0]);
+                    return Some(found[0].clone());
                 }
             }
         }
@@ -587,7 +589,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
                           let target_trait_ref = @ty::TraitRef {
                               def_id: target_def_id,
                               substs: ty::substs {
-                                  tps: copy target_substs.tps,
+                                  tps: target_substs.tps.clone(),
                                   self_r: target_substs.self_r,
                                   self_ty: Some(mt.ty)
                               }
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 768c4cd04e7..187a5eccdb1 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -208,9 +208,10 @@ impl CoherenceChecker {
 
                 match item.node {
                     item_impl(_, ref opt_trait, _, _) => {
-                        let opt_trait : ~[trait_ref] = opt_trait.iter()
-                                                                .transform(|x| copy *x)
-                                                                .collect();
+                        let opt_trait : ~[trait_ref] =
+                            opt_trait.iter()
+                                     .transform(|x| (*x).clone())
+                                     .collect();
                         self.check_implementation(item, opt_trait);
                     }
                     _ => {
@@ -358,14 +359,14 @@ impl CoherenceChecker {
             let new_generics = ty::Generics {
                 type_param_defs:
                     @vec::append(
-                        copy *impl_poly_type.generics.type_param_defs,
+                        (*impl_poly_type.generics.type_param_defs).clone(),
                         *new_method_ty.generics.type_param_defs),
                 region_param:
                     impl_poly_type.generics.region_param
             };
             let new_polytype = ty::ty_param_bounds_and_ty {
                 generics: new_generics,
-                ty: ty::mk_bare_fn(tcx, copy new_method_ty.fty)
+                ty: ty::mk_bare_fn(tcx, new_method_ty.fty.clone())
             };
             debug!("new_polytype=%s", new_polytype.repr(tcx));
 
@@ -901,7 +902,7 @@ impl CoherenceChecker {
 
             // XXX(sully): We could probably avoid this copy if there are no
             // default methods.
-            let mut methods = copy implementation.methods;
+            let mut methods = implementation.methods.clone();
             self.add_provided_methods_to_impl(&mut methods,
                                               &trait_ref.def_id,
                                               &implementation.did);
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 356d9bc79a7..5d39f1ae374 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -86,7 +86,7 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: &ast::crate) {
 }
 
 pub trait ToTy {
-    fn to_ty<RS:region_scope + Copy + 'static>(
+    fn to_ty<RS:region_scope + Clone + 'static>(
              &self,
              rs: &RS,
              ast_ty: &ast::Ty)
@@ -94,7 +94,7 @@ pub trait ToTy {
 }
 
 impl ToTy for CrateCtxt {
-    fn to_ty<RS:region_scope + Copy + 'static>(
+    fn to_ty<RS:region_scope + Clone + 'static>(
              &self,
              rs: &RS,
              ast_ty: &ast::Ty)
@@ -309,7 +309,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
         // create the type of `foo`, applying the substitution above
         let ty = ty::subst(tcx,
                            &substs,
-                           ty::mk_bare_fn(tcx, copy m.fty));
+                           ty::mk_bare_fn(tcx, m.fty.clone()));
 
         // create the type parameter definitions for `foo`, applying
         // the substitution to any traits that appear in their bounds.
@@ -569,27 +569,35 @@ pub fn compare_impl_method(tcx: ty::ctxt,
 
     // Create a bare fn type for trait/impl that includes self argument
     let trait_fty =
-        ty::mk_bare_fn(
-            tcx,
-            ty::BareFnTy {purity: trait_m.fty.purity,
-                          abis: trait_m.fty.abis,
-                          sig: ty::FnSig {
-                              bound_lifetime_names:
-                                  copy trait_m.fty.sig.bound_lifetime_names,
-                              inputs: trait_fn_args,
-                              output: trait_m.fty.sig.output
-                          }});
+        ty::mk_bare_fn(tcx,
+                       ty::BareFnTy {
+                            purity: trait_m.fty.purity,
+                            abis: trait_m.fty.abis,
+                            sig: ty::FnSig {
+                                bound_lifetime_names:
+                                    trait_m.fty
+                                           .sig
+                                           .bound_lifetime_names
+                                           .clone(),
+                                inputs: trait_fn_args,
+                                output: trait_m.fty.sig.output
+                            }
+                        });
     let impl_fty =
-        ty::mk_bare_fn(
-            tcx,
-            ty::BareFnTy {purity: impl_m.fty.purity,
-                          abis: impl_m.fty.abis,
-                          sig: ty::FnSig {
-                              bound_lifetime_names:
-                                  copy impl_m.fty.sig.bound_lifetime_names,
-                              inputs: impl_fn_args,
-                              output: impl_m.fty.sig.output
-                          }});
+        ty::mk_bare_fn(tcx,
+                       ty::BareFnTy {
+                            purity: impl_m.fty.purity,
+                            abis: impl_m.fty.abis,
+                            sig: ty::FnSig {
+                                bound_lifetime_names:
+                                    impl_m.fty
+                                          .sig
+                                          .bound_lifetime_names
+                                          .clone(),
+                                    inputs: impl_fn_args,
+                                    output: impl_m.fty.sig.output
+                            }
+                        });
 
     // Perform substitutions so that the trait/impl methods are expressed
     // in terms of the same set of type/region parameters:
@@ -730,8 +738,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
                           untransformed_rcvr_ty,
                           rcvr_ast_generics, rcvr_visibility,
                           &m.generics);
-        let fty =
-            ty::mk_bare_fn(tcx, copy mty.fty);
+        let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
         tcx.tcache.insert(
             local_def(m.id),
 
@@ -740,7 +747,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
             ty_param_bounds_and_ty {
                 generics: ty::Generics {
                     type_param_defs: @vec::append(
-                        copy *rcvr_ty_generics.type_param_defs,
+                        (*rcvr_ty_generics.type_param_defs).clone(),
                         *m_ty_generics.type_param_defs),
                     region_param: rcvr_ty_generics.region_param
                 },
diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs
index 03d243797b3..a6899d7150e 100644
--- a/src/librustc/middle/typeck/infer/coercion.rs
+++ b/src/librustc/middle/typeck/infer/coercion.rs
@@ -275,8 +275,10 @@ impl Coerce {
                b.inf_str(self.infcx));
 
         let fn_ty = match *sty_a {
-            ty::ty_closure(ref f) if f.sigil == ast::ManagedSigil => copy *f,
-            ty::ty_closure(ref f) if f.sigil == ast::OwnedSigil => copy *f,
+            ty::ty_closure(ref f) if f.sigil == ast::ManagedSigil ||
+                                     f.sigil == ast::OwnedSigil => {
+                (*f).clone()
+            }
             ty::ty_bare_fn(ref f) => {
                 return self.coerce_from_bare_fn(a, f, b);
             }
@@ -331,16 +333,16 @@ impl Coerce {
         }
 
         let fn_ty_b = match *sty_b {
-            ty::ty_closure(ref f) => {copy *f}
-            _ => {
-                return self.subtype(a, b);
-            }
+            ty::ty_closure(ref f) => (*f).clone(),
+            _ => return self.subtype(a, b),
         };
 
         let adj = @ty::AutoAddEnv(fn_ty_b.region, fn_ty_b.sigil);
-        let a_closure = ty::mk_closure(
-            self.infcx.tcx,
-            ty::ClosureTy {sig: copy fn_ty_a.sig, ..fn_ty_b});
+        let a_closure = ty::mk_closure(self.infcx.tcx,
+                                       ty::ClosureTy {
+                                            sig: fn_ty_a.sig.clone(),
+                                            ..fn_ty_b
+                                       });
         if_ok!(self.subtype(a_closure, b));
         Ok(Some(adj))
     }
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index fe32c2f7c4a..65fbd080561 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -241,13 +241,14 @@ pub fn super_substs<C:Combine>(
 
     do this.tps(a.tps, b.tps).chain |tps| {
         do this.self_tys(a.self_ty, b.self_ty).chain |self_ty| {
-            do relate_region_param(this, generics,
-                                   a.self_r, b.self_r).chain |self_r|
-            {
+            do relate_region_param(this,
+                                   generics,
+                                   a.self_r,
+                                   b.self_r).chain |self_r| {
                 Ok(substs {
                     self_r: self_r,
                     self_ty: self_ty,
-                    tps: /*bad*/copy tps
+                    tps: tps.clone()
                 })
             }
         }
@@ -425,7 +426,7 @@ pub fn super_fn_sigs<C:Combine>(
             .chain |inputs| {
         do this.tys(a_f.output, b_f.output).chain |output| {
             Ok(FnSig {bound_lifetime_names: opt_vec::Empty, // FIXME(#4846)
-                      inputs: /*bad*/copy inputs,
+                      inputs: inputs.clone(),
                       output: output})
         }
     }
@@ -515,7 +516,12 @@ pub fn super_tys<C:Combine>(
           do this.substs(&trait_def.generics, a_substs, b_substs).chain |substs| {
               do this.trait_stores(ty::terr_trait, a_store, b_store).chain |s| {
                   do this.bounds(a_bounds, b_bounds).chain |bounds| {
-                    Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s, a_mutbl, bounds))
+                    Ok(ty::mk_trait(tcx,
+                                    a_id,
+                                    substs.clone(),
+                                    s,
+                                    a_mutbl,
+                                    bounds))
                   }
               }
           }
diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs
index 53ae03922dc..b95d977bd43 100644
--- a/src/librustc/middle/typeck/infer/lattice.rs
+++ b/src/librustc/middle/typeck/infer/lattice.rs
@@ -71,39 +71,39 @@ impl LatticeValue for ty::t {
 }
 
 pub trait CombineFieldsLatticeMethods {
-    fn var_sub_var<T:Copy + InferStr + LatticeValue,
-                   V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(&self,
-                                                                    a_id: V,
-                                                                    b_id: V)
-                                                                    -> ures;
+    fn var_sub_var<T:Clone + InferStr + LatticeValue,
+                   V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(&self,
+                                                                     a_id: V,
+                                                                     b_id: V)
+                                                                     -> ures;
     /// make variable a subtype of T
-    fn var_sub_t<T:Copy + InferStr + LatticeValue,
-                 V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+    fn var_sub_t<T:Clone + InferStr + LatticeValue,
+                 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
                  &self,
                  a_id: V,
                  b: T)
                  -> ures;
-    fn t_sub_var<T:Copy + InferStr + LatticeValue,
-                 V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+    fn t_sub_var<T:Clone + InferStr + LatticeValue,
+                 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
                  &self,
                  a: T,
                  b_id: V)
                  -> ures;
-    fn merge_bnd<T:Copy + InferStr + LatticeValue>(
+    fn merge_bnd<T:Clone + InferStr + LatticeValue>(
                  &self,
                  a: &Bound<T>,
                  b: &Bound<T>,
                  lattice_op: LatticeOp<T>)
                  -> cres<Bound<T>>;
-    fn set_var_to_merged_bounds<T:Copy + InferStr + LatticeValue,
-                                V:Copy+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
+    fn set_var_to_merged_bounds<T:Clone + InferStr + LatticeValue,
+                                V:Clone+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
                                 &self,
                                 v_id: V,
                                 a: &Bounds<T>,
                                 b: &Bounds<T>,
                                 rank: uint)
                                 -> ures;
-    fn bnds<T:Copy + InferStr + LatticeValue>(
+    fn bnds<T:Clone + InferStr + LatticeValue>(
             &self,
             a: &Bound<T>,
             b: &Bound<T>)
@@ -111,8 +111,8 @@ pub trait CombineFieldsLatticeMethods {
 }
 
 impl CombineFieldsLatticeMethods for CombineFields {
-    fn var_sub_var<T:Copy + InferStr + LatticeValue,
-                   V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+    fn var_sub_var<T:Clone + InferStr + LatticeValue,
+                   V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
                    &self,
                    a_id: V,
                    b_id: V)
@@ -126,10 +126,10 @@ impl CombineFieldsLatticeMethods for CombineFields {
         // Need to make sub_id a subtype of sup_id.
         let node_a = self.infcx.get(a_id);
         let node_b = self.infcx.get(b_id);
-        let a_id = copy node_a.root;
-        let b_id = copy node_b.root;
-        let a_bounds = copy node_a.possible_types;
-        let b_bounds = copy node_b.possible_types;
+        let a_id = node_a.root.clone();
+        let b_id = node_b.root.clone();
+        let a_bounds = node_a.possible_types.clone();
+        let b_bounds = node_b.possible_types.clone();
 
         debug!("vars(%s=%s <: %s=%s)",
                a_id.to_str(), a_bounds.inf_str(self.infcx),
@@ -164,8 +164,8 @@ impl CombineFieldsLatticeMethods for CombineFields {
     }
 
     /// make variable a subtype of T
-    fn var_sub_t<T:Copy + InferStr + LatticeValue,
-                 V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+    fn var_sub_t<T:Clone + InferStr + LatticeValue,
+                 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
                  &self,
                  a_id: V,
                  b: T)
@@ -175,9 +175,9 @@ impl CombineFieldsLatticeMethods for CombineFields {
          * Make a variable (`a_id`) a subtype of the concrete type `b` */
 
         let node_a = self.infcx.get(a_id);
-        let a_id = copy node_a.root;
+        let a_id = node_a.root.clone();
         let a_bounds = &node_a.possible_types;
-        let b_bounds = &Bounds { lb: None, ub: Some(copy b) };
+        let b_bounds = &Bounds { lb: None, ub: Some(b.clone()) };
 
         debug!("var_sub_t(%s=%s <: %s)",
                a_id.to_str(),
@@ -188,8 +188,8 @@ impl CombineFieldsLatticeMethods for CombineFields {
             a_id, a_bounds, b_bounds, node_a.rank)
     }
 
-    fn t_sub_var<T:Copy + InferStr + LatticeValue,
-                 V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+    fn t_sub_var<T:Clone + InferStr + LatticeValue,
+                 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
                  &self,
                  a: T,
                  b_id: V)
@@ -198,9 +198,9 @@ impl CombineFieldsLatticeMethods for CombineFields {
          *
          * Make a concrete type (`a`) a subtype of the variable `b_id` */
 
-        let a_bounds = &Bounds { lb: Some(copy a), ub: None };
+        let a_bounds = &Bounds { lb: Some(a.clone()), ub: None };
         let node_b = self.infcx.get(b_id);
-        let b_id = copy node_b.root;
+        let b_id = node_b.root.clone();
         let b_bounds = &node_b.possible_types;
 
         debug!("t_sub_var(%s <: %s=%s)",
@@ -212,7 +212,7 @@ impl CombineFieldsLatticeMethods for CombineFields {
             b_id, a_bounds, b_bounds, node_b.rank)
     }
 
-    fn merge_bnd<T:Copy + InferStr + LatticeValue>(
+    fn merge_bnd<T:Clone + InferStr + LatticeValue>(
                  &self,
                  a: &Bound<T>,
                  b: &Bound<T>,
@@ -229,8 +229,8 @@ impl CombineFieldsLatticeMethods for CombineFields {
 
         match (a, b) {
             (&None,          &None) => Ok(None),
-            (&Some(_),       &None) => Ok(copy *a),
-            (&None,          &Some(_)) => Ok(copy *b),
+            (&Some(_),       &None) => Ok((*a).clone()),
+            (&None,          &Some(_)) => Ok((*b).clone()),
             (&Some(ref v_a), &Some(ref v_b)) => {
                 do lattice_op(self, v_a, v_b).chain |v| {
                     Ok(Some(v))
@@ -239,8 +239,8 @@ impl CombineFieldsLatticeMethods for CombineFields {
         }
     }
 
-    fn set_var_to_merged_bounds<T:Copy + InferStr + LatticeValue,
-                                V:Copy+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
+    fn set_var_to_merged_bounds<T:Clone + InferStr + LatticeValue,
+                                V:Clone+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
                                 &self,
                                 v_id: V,
                                 a: &Bounds<T>,
@@ -301,10 +301,10 @@ impl CombineFieldsLatticeMethods for CombineFields {
         uok()
     }
 
-    fn bnds<T:Copy + InferStr + LatticeValue>(&self,
-                                              a: &Bound<T>,
-                                              b: &Bound<T>)
-                                              -> ures {
+    fn bnds<T:Clone + InferStr + LatticeValue>(&self,
+                                               a: &Bound<T>,
+                                               b: &Bound<T>)
+                                               -> ures {
         debug!("bnds(%s <: %s)", a.inf_str(self.infcx),
                b.inf_str(self.infcx));
         let _r = indenter();
@@ -330,8 +330,8 @@ impl CombineFieldsLatticeMethods for CombineFields {
 
 pub trait LatticeDir {
     fn combine_fields(&self) -> CombineFields;
-    fn bnd<T:Copy>(&self, b: &Bounds<T>) -> Option<T>;
-    fn with_bnd<T:Copy>(&self, b: &Bounds<T>, t: T) -> Bounds<T>;
+    fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T>;
+    fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T>;
 }
 
 pub trait TyLatticeDir {
@@ -340,9 +340,9 @@ pub trait TyLatticeDir {
 
 impl LatticeDir for Lub {
     fn combine_fields(&self) -> CombineFields { **self }
-    fn bnd<T:Copy>(&self, b: &Bounds<T>) -> Option<T> { copy b.ub }
-    fn with_bnd<T:Copy>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
-        Bounds { ub: Some(t), ..copy *b }
+    fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.ub.clone() }
+    fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
+        Bounds { ub: Some(t), ..(*b).clone() }
     }
 }
 
@@ -354,9 +354,9 @@ impl TyLatticeDir for Lub {
 
 impl LatticeDir for Glb {
     fn combine_fields(&self) -> CombineFields { **self }
-    fn bnd<T:Copy>(&self, b: &Bounds<T>) -> Option<T> { copy b.lb }
-    fn with_bnd<T:Copy>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
-        Bounds { lb: Some(t), ..copy *b }
+    fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.lb.clone() }
+    fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
+        Bounds { lb: Some(t), ..(*b).clone() }
     }
 }
 
@@ -412,6 +412,7 @@ pub fn super_lattice_tys<L:LatticeDir + TyLatticeDir + Combine>(
 
 pub type LatticeDirOp<'self, T> = &'self fn(a: &T, b: &T) -> cres<T>;
 
+#[deriving(Clone)]
 pub enum LatticeVarResult<V,T> {
     VarResult(V),
     ValueResult(T)
@@ -433,8 +434,8 @@ pub enum LatticeVarResult<V,T> {
  *   result is a variable.  This is indicated with a `VarResult`
  *   return. */
 pub fn lattice_vars<L:LatticeDir + Combine,
-                    T:Copy + InferStr + LatticeValue,
-                    V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+                    T:Clone + InferStr + LatticeValue,
+                    V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
     this: &L,                           // defines whether we want LUB or GLB
     a_vid: V,                          // first variable
     b_vid: V,                          // second variable
@@ -442,8 +443,8 @@ pub fn lattice_vars<L:LatticeDir + Combine,
     -> cres<LatticeVarResult<V,T>> {
     let nde_a = this.infcx().get(a_vid);
     let nde_b = this.infcx().get(b_vid);
-    let a_vid = copy nde_a.root;
-    let b_vid = copy nde_b.root;
+    let a_vid = nde_a.root.clone();
+    let b_vid = nde_b.root.clone();
     let a_bounds = &nde_a.possible_types;
     let b_bounds = &nde_b.possible_types;
 
@@ -473,21 +474,21 @@ pub fn lattice_vars<L:LatticeDir + Combine,
     // Otherwise, we need to merge A and B into one variable.  We can
     // then use either variable as an upper bound:
     let cf = this.combine_fields();
-    do cf.var_sub_var(copy a_vid, copy b_vid).then {
-        Ok(VarResult(copy a_vid))
+    do cf.var_sub_var(a_vid.clone(), b_vid.clone()).then {
+        Ok(VarResult(a_vid.clone()))
     }
 }
 
 pub fn lattice_var_and_t<L:LatticeDir + Combine,
-                         T:Copy + InferStr + LatticeValue,
-                         V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+                         T:Clone + InferStr + LatticeValue,
+                         V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
     this: &L,
     a_id: V,
     b: &T,
     lattice_dir_op: LatticeDirOp<T>)
     -> cres<T> {
     let nde_a = this.infcx().get(a_id);
-    let a_id = copy nde_a.root;
+    let a_id = nde_a.root.clone();
     let a_bounds = &nde_a.possible_types;
 
     // The comments in this function are written for LUB, but they
@@ -509,10 +510,11 @@ pub fn lattice_var_and_t<L:LatticeDir + Combine,
             // If a does not have an upper bound, make b the upper bound of a
             // and then return b.
             debug!("bnd=None");
-            let a_bounds = this.with_bnd(a_bounds, copy *b);
+            let a_bounds = this.with_bnd(a_bounds, (*b).clone());
             do this.combine_fields().bnds(&a_bounds.lb, &a_bounds.ub).then {
-                this.infcx().set(copy a_id, Root(copy a_bounds, nde_a.rank));
-                Ok(copy *b)
+                this.infcx().set(a_id.clone(),
+                                 Root(a_bounds.clone(), nde_a.rank));
+                Ok((*b).clone())
             }
         }
     }
diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs
index 2a8d68c9e67..1f0fb135762 100644
--- a/src/librustc/middle/typeck/infer/mod.rs
+++ b/src/librustc/middle/typeck/infer/mod.rs
@@ -62,6 +62,8 @@ pub mod coercion;
 pub mod error_reporting;
 
 pub type Bound<T> = Option<T>;
+
+#[deriving(Clone)]
 pub struct Bounds<T> {
     lb: Bound<T>,
     ub: Bound<T>
@@ -96,6 +98,7 @@ pub struct InferCtxt {
 /// Why did we require that the two types be related?
 ///
 /// See `error_reporting.rs` for more details
+#[deriving(Clone)]
 pub enum TypeOrigin {
     // Not yet categorized in a better way
     Misc(span),
@@ -120,6 +123,7 @@ pub enum TypeOrigin {
 }
 
 /// See `error_reporting.rs` for more details
+#[deriving(Clone)]
 pub enum ValuePairs {
     Types(ty::expected_found<ty::t>),
     TraitRefs(ty::expected_found<@ty::TraitRef>),
@@ -129,6 +133,7 @@ pub enum ValuePairs {
 /// encounter an error or subtyping constraint.
 ///
 /// See `error_reporting.rs` for more details.
+#[deriving(Clone)]
 pub struct TypeTrace {
     origin: TypeOrigin,
     values: ValuePairs,
@@ -137,6 +142,7 @@ pub struct TypeTrace {
 /// The origin of a `r1 <= r2` constraint.
 ///
 /// See `error_reporting.rs` for more details
+#[deriving(Clone)]
 pub enum SubregionOrigin {
     // Arose from a subtyping relation
     Subtype(TypeTrace),
@@ -245,7 +251,7 @@ pub fn fixup_err_to_str(f: fixup_err) -> ~str {
     }
 }
 
-fn new_ValsAndBindings<V:Copy,T:Copy>() -> ValsAndBindings<V, T> {
+fn new_ValsAndBindings<V:Clone,T:Clone>() -> ValsAndBindings<V, T> {
     ValsAndBindings {
         vals: SmallIntMap::new(),
         bindings: ~[]
@@ -439,12 +445,12 @@ pub fn resolve_region(cx: @mut InferCtxt, r: ty::Region, modes: uint)
 }
 
 trait then {
-    fn then<T:Copy>(&self, f: &fn() -> Result<T,ty::type_err>)
+    fn then<T:Clone>(&self, f: &fn() -> Result<T,ty::type_err>)
         -> Result<T,ty::type_err>;
 }
 
 impl then for ures {
-    fn then<T:Copy>(&self, f: &fn() -> Result<T,ty::type_err>)
+    fn then<T:Clone>(&self, f: &fn() -> Result<T,ty::type_err>)
         -> Result<T,ty::type_err> {
         self.chain(|_i| f())
     }
@@ -467,11 +473,11 @@ trait CresCompare<T> {
     fn compare(&self, t: T, f: &fn() -> ty::type_err) -> cres<T>;
 }
 
-impl<T:Copy + Eq> CresCompare<T> for cres<T> {
+impl<T:Clone + Eq> CresCompare<T> for cres<T> {
     fn compare(&self, t: T, f: &fn() -> ty::type_err) -> cres<T> {
-        do (copy *self).chain |s| {
+        do (*self).clone().chain |s| {
             if s == t {
-                copy *self
+                (*self).clone()
             } else {
                 Err(f())
             }
@@ -483,10 +489,8 @@ pub fn uok() -> ures {
     Ok(())
 }
 
-fn rollback_to<V:Copy + Vid,T:Copy>(
-    vb: &mut ValsAndBindings<V, T>,
-    len: uint)
-{
+fn rollback_to<V:Clone + Vid,T:Clone>(vb: &mut ValsAndBindings<V, T>,
+                                      len: uint) {
     while vb.bindings.len() != len {
         let (vid, old_v) = vb.bindings.pop();
         vb.vals.insert(vid.to_uint(), old_v);
@@ -588,10 +592,10 @@ impl InferCtxt {
     }
 }
 
-fn next_simple_var<V:Copy,T:Copy>(
-        counter: &mut uint,
-        bindings: &mut ValsAndBindings<V,Option<T>>)
-     -> uint {
+fn next_simple_var<V:Clone,T:Clone>(counter: &mut uint,
+                                    bindings: &mut ValsAndBindings<V,
+                                                                   Option<T>>)
+                                    -> uint {
     let id = *counter;
     *counter += 1;
     bindings.vals.insert(id, Root(None, 0));
@@ -668,15 +672,17 @@ impl InferCtxt {
         // make up a dummy type just to reuse/abuse the resolve machinery
         let dummy0 = ty::mk_trait(self.tcx,
                                   trait_ref.def_id,
-                                  copy trait_ref.substs,
+                                  trait_ref.substs.clone(),
                                   ty::UniqTraitStore,
                                   ast::m_imm,
                                   ty::EmptyBuiltinBounds());
         let dummy1 = self.resolve_type_vars_if_possible(dummy0);
         match ty::get(dummy1).sty {
             ty::ty_trait(ref def_id, ref substs, _, _, _) => {
-                ty::TraitRef {def_id: *def_id,
-                              substs: copy *substs}
+                ty::TraitRef {
+                    def_id: *def_id,
+                    substs: (*substs).clone(),
+                }
             }
             _ => {
                 self.tcx.sess.bug(
diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs
index a7c3350d1d1..5ebbee8986b 100644
--- a/src/librustc/middle/typeck/infer/unify.rs
+++ b/src/librustc/middle/typeck/infer/unify.rs
@@ -18,6 +18,7 @@ use middle::typeck::infer::InferCtxt;
 use middle::typeck::infer::to_str::InferStr;
 use syntax::ast;
 
+#[deriving(Clone)]
 pub enum VarValue<V, T> {
     Redirect(V),
     Root(T, uint),
@@ -40,18 +41,18 @@ pub trait UnifyVid<T> {
 }
 
 pub trait UnifyInferCtxtMethods {
-    fn get<T:Copy,
-           V:Copy + Eq + Vid + UnifyVid<T>>(
+    fn get<T:Clone,
+           V:Clone + Eq + Vid + UnifyVid<T>>(
            &mut self,
            vid: V)
            -> Node<V, T>;
-    fn set<T:Copy + InferStr,
-           V:Copy + Vid + ToStr + UnifyVid<T>>(
+    fn set<T:Clone + InferStr,
+           V:Clone + Vid + ToStr + UnifyVid<T>>(
            &mut self,
            vid: V,
            new_v: VarValue<V, T>);
-    fn unify<T:Copy + InferStr,
-             V:Copy + Vid + ToStr + UnifyVid<T>>(
+    fn unify<T:Clone + InferStr,
+             V:Clone + Vid + ToStr + UnifyVid<T>>(
              &mut self,
              node_a: &Node<V, T>,
              node_b: &Node<V, T>)
@@ -59,8 +60,8 @@ pub trait UnifyInferCtxtMethods {
 }
 
 impl UnifyInferCtxtMethods for InferCtxt {
-    fn get<T:Copy,
-           V:Copy + Eq + Vid + UnifyVid<T>>(
+    fn get<T:Clone,
+           V:Clone + Eq + Vid + UnifyVid<T>>(
            &mut self,
            vid: V)
            -> Node<V, T> {
@@ -75,14 +76,14 @@ impl UnifyInferCtxtMethods for InferCtxt {
         let vb = UnifyVid::appropriate_vals_and_bindings(self);
         return helper(tcx, vb, vid);
 
-        fn helper<T:Copy, V:Copy+Eq+Vid>(
+        fn helper<T:Clone, V:Clone+Eq+Vid>(
             tcx: ty::ctxt,
             vb: &mut ValsAndBindings<V,T>,
             vid: V) -> Node<V, T>
         {
             let vid_u = vid.to_uint();
             let var_val = match vb.vals.find(&vid_u) {
-                Some(&ref var_val) => copy *var_val,
+                Some(&ref var_val) => (*var_val).clone(),
                 None => {
                     tcx.sess.bug(fmt!(
                         "failed lookup of vid `%u`", vid_u));
@@ -90,11 +91,11 @@ impl UnifyInferCtxtMethods for InferCtxt {
             };
             match var_val {
                 Redirect(vid) => {
-                    let node: Node<V,T> = helper(tcx, vb, copy vid);
+                    let node: Node<V,T> = helper(tcx, vb, vid.clone());
                     if node.root != vid {
                         // Path compression
                         vb.vals.insert(vid.to_uint(),
-                                       Redirect(copy node.root));
+                                       Redirect(node.root.clone()));
                     }
                     node
                 }
@@ -105,8 +106,8 @@ impl UnifyInferCtxtMethods for InferCtxt {
         }
     }
 
-    fn set<T:Copy + InferStr,
-           V:Copy + Vid + ToStr + UnifyVid<T>>(
+    fn set<T:Clone + InferStr,
+           V:Clone + Vid + ToStr + UnifyVid<T>>(
            &mut self,
            vid: V,
            new_v: VarValue<V, T>) {
@@ -119,13 +120,13 @@ impl UnifyInferCtxtMethods for InferCtxt {
                vid.to_str(), new_v.inf_str(self));
 
         let vb = UnifyVid::appropriate_vals_and_bindings(self);
-        let old_v = copy *vb.vals.get(&vid.to_uint());
-        vb.bindings.push((copy vid, old_v));
+        let old_v = (*vb.vals.get(&vid.to_uint())).clone();
+        vb.bindings.push((vid.clone(), old_v));
         vb.vals.insert(vid.to_uint(), new_v);
     }
 
-    fn unify<T:Copy + InferStr,
-             V:Copy + Vid + ToStr + UnifyVid<T>>(
+    fn unify<T:Clone + InferStr,
+             V:Clone + Vid + ToStr + UnifyVid<T>>(
              &mut self,
              node_a: &Node<V, T>,
              node_b: &Node<V, T>)
@@ -141,18 +142,18 @@ impl UnifyInferCtxtMethods for InferCtxt {
         if node_a.rank > node_b.rank {
             // a has greater rank, so a should become b's parent,
             // i.e., b should redirect to a.
-            self.set(copy node_b.root, Redirect(copy node_a.root));
-            (copy node_a.root, node_a.rank)
+            self.set(node_b.root.clone(), Redirect(node_a.root.clone()));
+            (node_a.root.clone(), node_a.rank)
         } else if node_a.rank < node_b.rank {
             // b has greater rank, so a should redirect to b.
-            self.set(copy node_a.root, Redirect(copy node_b.root));
-            (copy node_b.root, node_b.rank)
+            self.set(node_a.root.clone(), Redirect(node_b.root.clone()));
+            (node_b.root.clone(), node_b.rank)
         } else {
             // If equal, redirect one to the other and increment the
             // other's rank.
             assert_eq!(node_a.rank, node_b.rank);
-            self.set(copy node_b.root, Redirect(copy node_a.root));
-            (copy node_a.root, node_a.rank + 1)
+            self.set(node_b.root.clone(), Redirect(node_a.root.clone()));
+            (node_a.root.clone(), node_a.rank + 1)
         }
     }
 
@@ -179,15 +180,15 @@ pub fn mk_err<T:SimplyUnifiable>(a_is_expected: bool,
 }
 
 pub trait InferCtxtMethods {
-    fn simple_vars<T:Copy + Eq + InferStr + SimplyUnifiable,
-                   V:Copy + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
+    fn simple_vars<T:Clone + Eq + InferStr + SimplyUnifiable,
+                   V:Clone + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
                    &mut self,
                    a_is_expected: bool,
                    a_id: V,
                    b_id: V)
                    -> ures;
-    fn simple_var_t<T:Copy + Eq + InferStr + SimplyUnifiable,
-                    V:Copy + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
+    fn simple_var_t<T:Clone + Eq + InferStr + SimplyUnifiable,
+                    V:Clone + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
                     &mut self,
                     a_is_expected: bool,
                     a_id: V,
@@ -196,8 +197,8 @@ pub trait InferCtxtMethods {
 }
 
 impl InferCtxtMethods for InferCtxt {
-    fn simple_vars<T:Copy + Eq + InferStr + SimplyUnifiable,
-                   V:Copy + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
+    fn simple_vars<T:Clone + Eq + InferStr + SimplyUnifiable,
+                   V:Clone + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
                    &mut self,
                    a_is_expected: bool,
                    a_id: V,
@@ -212,20 +213,22 @@ impl InferCtxtMethods for InferCtxt {
 
         let node_a = self.get(a_id);
         let node_b = self.get(b_id);
-        let a_id = copy node_a.root;
-        let b_id = copy node_b.root;
+        let a_id = node_a.root.clone();
+        let b_id = node_b.root.clone();
 
         if a_id == b_id { return uok(); }
 
         let combined = match (&node_a.possible_types, &node_b.possible_types)
         {
             (&None, &None) => None,
-            (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(copy *v),
+            (&Some(ref v), &None) | (&None, &Some(ref v)) => {
+                Some((*v).clone())
+            }
             (&Some(ref v1), &Some(ref v2)) => {
                 if *v1 != *v2 {
-                    return mk_err(a_is_expected, copy *v1, copy *v2);
+                    return mk_err(a_is_expected, (*v1).clone(), (*v2).clone())
                 }
-                Some(copy *v1)
+                Some((*v1).clone())
             }
         };
 
@@ -234,8 +237,8 @@ impl InferCtxtMethods for InferCtxt {
         return uok();
     }
 
-    fn simple_var_t<T:Copy + Eq + InferStr + SimplyUnifiable,
-                    V:Copy + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
+    fn simple_var_t<T:Clone + Eq + InferStr + SimplyUnifiable,
+                    V:Clone + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
                     &mut self,
                     a_is_expected: bool,
                     a_id: V,
@@ -249,7 +252,7 @@ impl InferCtxtMethods for InferCtxt {
          * `b`. */
 
         let node_a = self.get(a_id);
-        let a_id = copy node_a.root;
+        let a_id = node_a.root.clone();
 
         match node_a.possible_types {
             None => {
@@ -261,7 +264,7 @@ impl InferCtxtMethods for InferCtxt {
                 if *a_t == b {
                     return uok();
                 } else {
-                    return mk_err(a_is_expected, copy *a_t, b);
+                    return mk_err(a_is_expected, (*a_t).clone(), b);
                 }
             }
         }
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index b8b8ab3145d..5f68f439eba 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -75,7 +75,7 @@ pub mod infer;
 pub mod collect;
 pub mod coherence;
 
-#[deriving(Encodable, Decodable)]
+#[deriving(Clone, Encodable, Decodable)]
 pub enum method_origin {
     // supertrait method invoked on "self" inside a default method
     // first field is supertrait ID;
@@ -99,7 +99,7 @@ pub enum method_origin {
 
 // details for a method invoked with a receiver whose type is a type parameter
 // with a bounded trait.
-#[deriving(Encodable, Decodable)]
+#[deriving(Clone, Encodable, Decodable)]
 pub struct method_param {
     // the trait containing the method to be invoked
     trait_id: ast::def_id,
@@ -115,6 +115,7 @@ pub struct method_param {
     bound_num: uint,
 }
 
+#[deriving(Clone)]
 pub struct method_map_entry {
     // the type of the self parameter, which is not reflected in the fn type
     // (FIXME #3446)
@@ -138,6 +139,7 @@ pub type vtable_param_res = @~[vtable_origin];
 // Resolutions for bounds of all parameters, left to right, for a given path.
 pub type vtable_res = @~[vtable_param_res];
 
+#[deriving(Clone)]
 pub enum vtable_origin {
     /*
       Statically known vtable. def_id gives the class or impl item
@@ -215,7 +217,7 @@ pub fn write_tpt_to_tcx(tcx: ty::ctxt,
                         tpt: &ty::ty_param_substs_and_ty) {
     write_ty_to_tcx(tcx, node_id, tpt.ty);
     if !tpt.substs.tps.is_empty() {
-        write_substs_to_tcx(tcx, node_id, copy tpt.substs.tps);
+        write_substs_to_tcx(tcx, node_id, tpt.substs.tps.clone());
     }
 }
 
diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs
index 91c875559fe..2f319687f6c 100644
--- a/src/librustc/middle/typeck/rscope.rs
+++ b/src/librustc/middle/typeck/rscope.rs
@@ -30,6 +30,7 @@ pub trait region_scope {
                       -> Result<ty::Region, RegionError>;
 }
 
+#[deriving(Clone)]
 pub enum empty_rscope { empty_rscope }
 impl region_scope for empty_rscope {
     fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
@@ -48,6 +49,7 @@ impl region_scope for empty_rscope {
     }
 }
 
+#[deriving(Clone)]
 pub struct RegionParamNames(OptVec<ast::ident>);
 
 impl RegionParamNames {
@@ -121,6 +123,7 @@ impl RegionParamNames {
     }
 }
 
+#[deriving(Clone)]
 struct RegionParameterization {
     variance: ty::region_variance,
     region_param_names: RegionParamNames,
@@ -143,6 +146,7 @@ impl RegionParameterization {
     }
 }
 
+#[deriving(Clone)]
 pub struct MethodRscope {
     explicit_self: ast::explicit_self_,
     variance: Option<ty::region_variance>,
@@ -166,7 +170,7 @@ impl MethodRscope {
     }
 
     pub fn region_param_names(&self) -> RegionParamNames {
-        copy self.region_param_names
+        self.region_param_names.clone()
     }
 }
 
@@ -206,6 +210,7 @@ impl region_scope for MethodRscope {
     }
 }
 
+#[deriving(Clone)]
 pub struct type_rscope(Option<RegionParameterization>);
 
 impl type_rscope {
@@ -268,11 +273,21 @@ pub struct binding_rscope {
     region_param_names: RegionParamNames,
 }
 
-pub fn in_binding_rscope<RS:region_scope + Copy + 'static>(
+impl Clone for binding_rscope {
+    fn clone(&self) -> binding_rscope {
+        binding_rscope {
+            base: self.base,
+            anon_bindings: self.anon_bindings,
+            region_param_names: self.region_param_names.clone(),
+        }
+    }
+}
+
+pub fn in_binding_rscope<RS:region_scope + Clone + 'static>(
         this: &RS,
         region_param_names: RegionParamNames)
      -> binding_rscope {
-    let base = @copy *this;
+    let base = @(*this).clone();
     let base = base as @region_scope;
     binding_rscope {
         base: base,
diff --git a/src/librustc/rustc.rs b/src/librustc/rustc.rs
index 6f638959bc8..a2e6527489c 100644
--- a/src/librustc/rustc.rs
+++ b/src/librustc/rustc.rs
@@ -116,6 +116,7 @@ pub mod lib {
 // macros.
 /*
 mod std {
+    pub use std::clone;
     pub use std::cmp;
     pub use std::os;
     pub use std::str;
@@ -184,9 +185,12 @@ Available lint options:
 pub fn describe_debug_flags() {
     io::println(fmt!("\nAvailable debug options:\n"));
     let r = session::debugging_opts_map();
-    for r.iter().advance |pair| {
-        let (name, desc, _) = /*bad*/copy *pair;
-        io::println(fmt!("    -Z %-20s -- %s", name, desc));
+    for r.iter().advance |tuple| {
+        match *tuple {
+            (ref name, ref desc, _) => {
+                io::println(fmt!("    -Z %-20s -- %s", *name, *desc));
+            }
+        }
     }
 }
 
@@ -194,7 +198,7 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) {
     // Don't display log spew by default. Can override with RUST_LOG.
     ::std::logging::console_off();
 
-    let mut args = /*bad*/copy *args;
+    let mut args = (*args).clone();
     let binary = args.shift().to_managed();
 
     if args.is_empty() { usage(binary); return; }
diff --git a/src/librustc/util/enum_set.rs b/src/librustc/util/enum_set.rs
index 3ce645e012b..2466c373f23 100644
--- a/src/librustc/util/enum_set.rs
+++ b/src/librustc/util/enum_set.rs
@@ -10,7 +10,7 @@
 
 use std::iterator::Iterator;
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct EnumSet<E> {
     // We must maintain the invariant that no bits are set
     // for which no variant exists
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 84f20d70bf0..09725a03a14 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -832,7 +832,7 @@ impl UserString for ty::TraitRef {
         let path = ty::item_path(tcx, self.def_id);
         let base = ast_map::path_to_str(path, tcx.sess.intr());
         if tcx.sess.verbose() && self.substs.self_ty.is_some() {
-            let mut all_tps = copy self.substs.tps;
+            let mut all_tps = self.substs.tps.clone();
             for self.substs.self_ty.iter().advance |&t| { all_tps.push(t); }
             parameterized(tcx, base, self.substs.self_r, all_tps)
         } else {
diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs
index 6d7d7911468..b20d8cab2a4 100644
--- a/src/librustdoc/astsrv.rs
+++ b/src/librustdoc/astsrv.rs
@@ -51,11 +51,11 @@ pub struct Srv {
 }
 
 pub fn from_str<T>(source: ~str, owner: SrvOwner<T>) -> T {
-    run(owner, copy source, parse::from_str_sess)
+    run(owner, source.clone(), parse::from_str_sess)
 }
 
 pub fn from_file<T>(file: ~str, owner: SrvOwner<T>) -> T {
-    run(owner, copy file, |sess, f| parse::from_file_sess(sess, &Path(f)))
+    run(owner, file.clone(), |sess, f| parse::from_file_sess(sess, &Path(f)))
 }
 
 fn run<T>(owner: SrvOwner<T>, source: ~str, parse: Parser) -> T {
@@ -117,7 +117,8 @@ fn build_ctxt(sess: Session,
                                                      copy sess.opts.cfg, ast);
     let ast = config::strip_unconfigured_items(ast);
     let ast = syntax::ext::expand::expand_crate(sess.parse_sess,
-                                                copy sess.opts.cfg, ast);
+                                                sess.opts.cfg.clone(),
+                                                ast);
     let ast = front::test::modify_for_testing(sess, ast);
     let ast_map = ast_map::map_crate(sess.diagnostic(), ast);
 
diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs
index 3c7d5091172..cc274e26f5b 100644
--- a/src/librustdoc/attr_pass.rs
+++ b/src/librustdoc/attr_pass.rs
@@ -61,17 +61,17 @@ fn fold_crate(
     let doc = fold::default_seq_fold_crate(fold, doc);
 
     let attrs = do astsrv::exec(srv) |ctxt| {
-        let attrs = copy ctxt.ast.node.attrs;
+        let attrs = ctxt.ast.node.attrs.clone();
         attr_parser::parse_crate(attrs)
     };
 
     doc::CrateDoc {
         topmod: doc::ModDoc {
             item: doc::ItemDoc {
-                name: (copy attrs.name).get_or_default(doc.topmod.name()),
-                .. copy doc.topmod.item
+                name: attrs.name.clone().get_or_default(doc.topmod.name()),
+                .. doc.topmod.item.clone()
             },
-            .. copy doc.topmod
+            .. doc.topmod.clone()
         }
     }
 }
@@ -87,7 +87,7 @@ fn fold_item(
     let desc = if doc.id == ast::crate_node_id {
         // This is the top-level mod, use the crate attributes
         do astsrv::exec(srv) |ctxt| {
-            attr_parser::parse_desc(copy ctxt.ast.node.attrs)
+            attr_parser::parse_desc(ctxt.ast.node.attrs.clone())
         }
     } else {
         parse_item_attrs(srv, doc.id, attr_parser::parse_desc)
@@ -105,8 +105,8 @@ fn parse_item_attrs<T:Send>(
     parse_attrs: ~fn(a: ~[ast::attribute]) -> T) -> T {
     do astsrv::exec(srv) |ctxt| {
         let attrs = match ctxt.ast_map.get_copy(&id) {
-            ast_map::node_item(item, _) => copy item.attrs,
-            ast_map::node_foreign_item(item, _, _, _) => copy item.attrs,
+            ast_map::node_item(item, _) => item.attrs.clone(),
+            ast_map::node_foreign_item(item, _, _, _) => item.attrs.clone(),
             _ => fail!("parse_item_attrs: not an item")
         };
         parse_attrs(attrs)
@@ -124,21 +124,21 @@ fn fold_enum(
 
     doc::EnumDoc {
         variants: do doc.variants.iter().transform |variant| {
-            let variant = copy *variant;
+            let variant = (*variant).clone();
             let desc = {
-                let variant = copy variant;
+                let variant = variant.clone();
                 do astsrv::exec(srv.clone()) |ctxt| {
                     match ctxt.ast_map.get_copy(&doc_id) {
                         ast_map::node_item(@ast::item {
                             node: ast::item_enum(ref enum_definition, _), _
                         }, _) => {
                             let ast_variant =
-                                copy *enum_definition.variants.iter().find_(|v| {
+                                (*enum_definition.variants.iter().find_(|v| {
                                     to_str(v.node.name) == variant.name
-                                }).get();
+                                }).get()).clone();
 
                             attr_parser::parse_desc(
-                                copy ast_variant.node.attrs)
+                                ast_variant.node.attrs.clone())
                         }
                         _ => {
                             fail!("Enum variant %s has id that's not bound to an enum item",
@@ -165,7 +165,7 @@ fn fold_trait(
     let doc = fold::default_seq_fold_trait(fold, doc);
 
     doc::TraitDoc {
-        methods: merge_method_attrs(srv, doc.id(), copy doc.methods),
+        methods: merge_method_attrs(srv, doc.id(), doc.methods.clone()),
         .. doc
     }
 }
@@ -183,13 +183,13 @@ fn merge_method_attrs(
                 node: ast::item_trait(_, _, ref methods), _
             }, _) => {
                 methods.iter().transform(|method| {
-                    match copy *method {
+                    match (*method).clone() {
                         ast::required(ty_m) => {
                             (to_str(ty_m.ident),
-                             attr_parser::parse_desc(copy ty_m.attrs))
+                             attr_parser::parse_desc(ty_m.attrs.clone()))
                         }
                         ast::provided(m) => {
-                            (to_str(m.ident), attr_parser::parse_desc(copy m.attrs))
+                            (to_str(m.ident), attr_parser::parse_desc(m.attrs.clone()))
                         }
                     }
                 }).collect()
@@ -199,7 +199,7 @@ fn merge_method_attrs(
             }, _) => {
                 methods.iter().transform(|method| {
                     (to_str(method.ident),
-                     attr_parser::parse_desc(copy method.attrs))
+                     attr_parser::parse_desc(method.attrs.clone()))
                 }).collect()
             }
             _ => fail!("unexpected item")
@@ -212,7 +212,7 @@ fn merge_method_attrs(
 
         doc::MethodDoc {
             desc: desc,
-            .. copy *doc
+            .. (*doc).clone()
         }
     }.collect()
 }
@@ -226,7 +226,7 @@ fn fold_impl(
     let doc = fold::default_seq_fold_impl(fold, doc);
 
     doc::ImplDoc {
-        methods: merge_method_attrs(srv, doc.id(), copy doc.methods),
+        methods: merge_method_attrs(srv, doc.id(), doc.methods.clone()),
         .. doc
     }
 }
@@ -240,7 +240,7 @@ mod test {
     use extract;
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             run(srv.clone(), doc)
         }
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index dd929fb143b..675ff7a8b95 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -19,7 +19,7 @@ use std::vec;
 use extra::getopts;
 
 /// The type of document to output
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum OutputFormat {
     /// Markdown
     pub Markdown,
@@ -28,7 +28,7 @@ pub enum OutputFormat {
 }
 
 /// How to organize the output
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum OutputStyle {
     /// All in a single document
     pub DocPerCrate,
@@ -37,6 +37,7 @@ pub enum OutputStyle {
 }
 
 /// The configuration for a rustdoc session
+#[deriving(Clone)]
 pub struct Config {
     input_crate: Path,
     output_dir: Path,
@@ -45,10 +46,6 @@ pub struct Config {
     pandoc_cmd: Option<~str>
 }
 
-impl Clone for Config {
-    fn clone(&self) -> Config { copy *self }
-}
-
 fn opt_output_dir() -> ~str { ~"output-dir" }
 fn opt_output_format() -> ~str { ~"output-format" }
 fn opt_output_style() -> ~str { ~"output-style" }
@@ -84,7 +81,7 @@ pub fn usage() {
 
 pub fn default_config(input_crate: &Path) -> Config {
     Config {
-        input_crate: copy *input_crate,
+        input_crate: (*input_crate).clone(),
         output_dir: Path("."),
         output_format: PandocHtml,
         output_style: DocPerMod,
@@ -145,21 +142,21 @@ fn config_from_opts(
         let output_dir = getopts::opt_maybe_str(matches, opt_output_dir());
         let output_dir = output_dir.map(|s| Path(*s));
         result::Ok(Config {
-            output_dir: output_dir.get_or_default(copy config.output_dir),
+            output_dir: output_dir.get_or_default(config.output_dir.clone()),
             .. config
         })
     };
     let result = do result::chain(result) |config| {
         let output_format = getopts::opt_maybe_str(
             matches, opt_output_format());
-        do output_format.map_default(result::Ok(copy config))
+        do output_format.map_default(result::Ok(config.clone()))
             |output_format| {
             do result::chain(parse_output_format(*output_format))
                 |output_format| {
 
                 result::Ok(Config {
                     output_format: output_format,
-                    .. copy config
+                    .. config.clone()
                 })
             }
         }
@@ -167,13 +164,13 @@ fn config_from_opts(
     let result = do result::chain(result) |config| {
         let output_style =
             getopts::opt_maybe_str(matches, opt_output_style());
-        do output_style.map_default(result::Ok(copy config))
+        do output_style.map_default(result::Ok(config.clone()))
             |output_style| {
             do result::chain(parse_output_style(*output_style))
                 |output_style| {
                 result::Ok(Config {
                     output_style: output_style,
-                    .. copy config
+                    .. config.clone()
                 })
             }
         }
@@ -186,7 +183,7 @@ fn config_from_opts(
         do result::chain(pandoc_cmd) |pandoc_cmd| {
             result::Ok(Config {
                 pandoc_cmd: pandoc_cmd,
-                .. copy config
+                .. config.clone()
             })
         }
     };
@@ -237,7 +234,7 @@ pub fn maybe_find_pandoc(
     };
 
     match pandoc {
-        Some(x) => Ok(Some(copy *x)), // ugly, shouldn't be doubly wrapped
+        Some(x) => Ok(Some((*x).clone())), // ugly, shouldn't be doubly wrapped
         None => Err(~"couldn't find pandoc")
     }
 }
diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs
index 9554db85e27..9e1dffb989b 100644
--- a/src/librustdoc/desc_to_brief_pass.rs
+++ b/src/librustdoc/desc_to_brief_pass.rs
@@ -49,7 +49,7 @@ fn fold_item(fold: &fold::Fold<()>, doc: doc::ItemDoc) -> doc::ItemDoc {
     let doc = fold::default_seq_fold_item(fold, doc);
 
     doc::ItemDoc {
-        brief: extract(copy doc.desc),
+        brief: extract(doc.desc.clone()),
         .. doc
     }
 }
@@ -59,8 +59,8 @@ fn fold_trait(fold: &fold::Fold<()>, doc: doc::TraitDoc) -> doc::TraitDoc {
 
     doc::TraitDoc {
         methods: doc.methods.map(|doc| doc::MethodDoc {
-            brief: extract(copy doc.desc),
-            .. copy *doc
+            brief: extract(doc.desc.clone()),
+            .. (*doc).clone()
         }),
         .. doc
     }
@@ -71,8 +71,8 @@ fn fold_impl(fold: &fold::Fold<()>, doc: doc::ImplDoc) -> doc::ImplDoc {
 
     doc::ImplDoc {
         methods: doc.methods.map(|doc| doc::MethodDoc {
-            brief: extract(copy doc.desc),
-            .. copy *doc
+            brief: extract(doc.desc.clone()),
+            .. (*doc).clone()
         }),
         .. doc
     }
@@ -83,13 +83,13 @@ pub fn extract(desc: Option<~str>) -> Option<~str> {
         return None
     }
 
-    parse_desc((copy desc).get())
+    parse_desc(desc.clone().get())
 }
 
 fn parse_desc(desc: ~str) -> Option<~str> {
     static MAX_BRIEF_LEN: uint = 120u;
 
-    match first_sentence(copy desc) {
+    match first_sentence(desc.clone()) {
       Some(first_sentence) => {
         if first_sentence.len() <= MAX_BRIEF_LEN {
             Some(first_sentence)
@@ -180,7 +180,7 @@ mod test {
     use extract;
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             let doc = (attr_pass::mk_pass().f)(srv.clone(), doc);
             run(srv.clone(), doc)
@@ -223,7 +223,7 @@ mod test {
     #[test]
     fn should_promote_short_descs() {
         let desc = Some(~"desc");
-        let brief = extract(copy desc);
+        let brief = extract(desc.clone());
         assert_eq!(brief, desc);
     }
 
diff --git a/src/librustdoc/doc.rs b/src/librustdoc/doc.rs
index ffb4642be81..9d173e271eb 100644
--- a/src/librustdoc/doc.rs
+++ b/src/librustdoc/doc.rs
@@ -15,18 +15,18 @@ use doc;
 
 pub type AstId = int;
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct Doc {
     pages: ~[Page]
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum Page {
     CratePage(CrateDoc),
     ItemPage(ItemTag)
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum Implementation {
     Required,
     Provided,
@@ -36,7 +36,7 @@ pub enum Implementation {
  * Most rustdocs can be parsed into 'sections' according to their markdown
  * headers
  */
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct Section {
     header: ~str,
     body: ~str
@@ -45,12 +45,12 @@ pub struct Section {
 // FIXME (#2596): We currently give topmod the name of the crate.  There
 // would probably be fewer special cases if the crate had its own name
 // and topmod's name was the empty string.
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct CrateDoc {
     topmod: ModDoc
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum ItemTag {
     ModTag(ModDoc),
     NmodTag(NmodDoc),
@@ -63,7 +63,7 @@ pub enum ItemTag {
     StructTag(StructDoc)
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct ItemDoc {
     id: AstId,
     name: ~str,
@@ -75,20 +75,20 @@ pub struct ItemDoc {
     reexport: bool
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct SimpleItemDoc {
     item: ItemDoc,
     sig: Option<~str>
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct ModDoc {
     item: ItemDoc,
     items: ~[ItemTag],
     index: Option<Index>
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct NmodDoc {
     item: ItemDoc,
     fns: ~[FnDoc],
@@ -99,26 +99,26 @@ pub type ConstDoc = SimpleItemDoc;
 
 pub type FnDoc = SimpleItemDoc;
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct EnumDoc {
     item: ItemDoc,
     variants: ~[VariantDoc]
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct VariantDoc {
     name: ~str,
     desc: Option<~str>,
     sig: Option<~str>
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct TraitDoc {
     item: ItemDoc,
     methods: ~[MethodDoc]
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct MethodDoc {
     name: ~str,
     brief: Option<~str>,
@@ -128,7 +128,7 @@ pub struct MethodDoc {
     implementation: Implementation,
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct ImplDoc {
     item: ItemDoc,
     bounds_str: Option<~str>,
@@ -139,14 +139,14 @@ pub struct ImplDoc {
 
 pub type TyDoc = SimpleItemDoc;
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct StructDoc {
     item: ItemDoc,
     fields: ~[~str],
     sig: Option<~str>
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct Index {
     entries: ~[IndexEntry]
 }
@@ -161,7 +161,7 @@ pub struct Index {
  * * brief - The brief description
  * * link - A format-specific string representing the link target
  */
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct IndexEntry {
     kind: ~str,
     name: ~str,
@@ -172,7 +172,7 @@ pub struct IndexEntry {
 impl Doc {
     pub fn CrateDoc(&self) -> CrateDoc {
         self.pages.iter().fold(None, |_m, page| {
-            match copy *page {
+            match (*page).clone() {
               doc::CratePage(doc) => Some(doc),
               _ => None
             }
@@ -180,7 +180,7 @@ impl Doc {
     }
 
     pub fn cratemod(&self) -> ModDoc {
-        copy self.CrateDoc().topmod
+        self.CrateDoc().topmod.clone()
     }
 }
 
@@ -188,7 +188,7 @@ macro_rules! filt_mapper {
     ($vec:expr, $pat:pat) => {
         do ($vec).iter().filter_map |thing| {
             match thing {
-                &$pat => Some(copy *x),
+                &$pat => Some((*x).clone()),
                 _ => None
             }
         }.collect()
@@ -298,45 +298,59 @@ pub trait Item {
 impl Item for ItemTag {
     fn item(&self) -> ItemDoc {
         match self {
-          &doc::ModTag(ref doc) => copy doc.item,
-          &doc::NmodTag(ref doc) => copy doc.item,
-          &doc::FnTag(ref doc) => copy doc.item,
-          &doc::ConstTag(ref doc) => copy doc.item,
-          &doc::EnumTag(ref doc) => copy doc.item,
-          &doc::TraitTag(ref doc) => copy doc.item,
-          &doc::ImplTag(ref doc) => copy doc.item,
-          &doc::TyTag(ref doc) => copy doc.item,
-          &doc::StructTag(ref doc) => copy doc.item
+          &doc::ModTag(ref doc) => doc.item.clone(),
+          &doc::NmodTag(ref doc) => doc.item.clone(),
+          &doc::FnTag(ref doc) => doc.item.clone(),
+          &doc::ConstTag(ref doc) => doc.item.clone(),
+          &doc::EnumTag(ref doc) => doc.item.clone(),
+          &doc::TraitTag(ref doc) => doc.item.clone(),
+          &doc::ImplTag(ref doc) => doc.item.clone(),
+          &doc::TyTag(ref doc) => doc.item.clone(),
+          &doc::StructTag(ref doc) => doc.item.clone(),
         }
     }
 }
 
 impl Item for SimpleItemDoc {
-    fn item(&self) -> ItemDoc { copy self.item }
+    fn item(&self) -> ItemDoc {
+        self.item.clone()
+    }
 }
 
 impl Item for ModDoc {
-    fn item(&self) -> ItemDoc { copy self.item }
+    fn item(&self) -> ItemDoc {
+        self.item.clone()
+    }
 }
 
 impl Item for NmodDoc {
-    fn item(&self) -> ItemDoc { copy self.item }
+    fn item(&self) -> ItemDoc {
+        self.item.clone()
+    }
 }
 
 impl Item for EnumDoc {
-    fn item(&self) -> ItemDoc { copy self.item }
+    fn item(&self) -> ItemDoc {
+        self.item.clone()
+    }
 }
 
 impl Item for TraitDoc {
-    fn item(&self) -> ItemDoc { copy self.item }
+    fn item(&self) -> ItemDoc {
+        self.item.clone()
+    }
 }
 
 impl Item for ImplDoc {
-    fn item(&self) -> ItemDoc { copy self.item }
+    fn item(&self) -> ItemDoc {
+        self.item.clone()
+    }
 }
 
 impl Item for StructDoc {
-    fn item(&self) -> ItemDoc { copy self.item }
+    fn item(&self) -> ItemDoc {
+        self.item.clone()
+    }
 }
 
 pub trait ItemUtils {
@@ -354,22 +368,22 @@ impl<A:Item> ItemUtils for A {
     }
 
     fn name(&self) -> ~str {
-        copy self.item().name
+        self.item().name.clone()
     }
 
     fn path(&self) -> ~[~str] {
-        copy self.item().path
+        self.item().path.clone()
     }
 
     fn brief(&self) -> Option<~str> {
-        copy self.item().brief
+        self.item().brief.clone()
     }
 
     fn desc(&self) -> Option<~str> {
-        copy self.item().desc
+        self.item().desc.clone()
     }
 
     fn sections(&self) -> ~[Section] {
-        copy self.item().sections
+        self.item().sections.clone()
     }
 }
diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs
index 01b77a985fe..095066b1647 100644
--- a/src/librustdoc/extract.rs
+++ b/src/librustdoc/extract.rs
@@ -39,7 +39,7 @@ pub fn from_srv(
     //! Use the AST service to create a document tree
 
     do astsrv::exec(srv) |ctxt| {
-        extract(ctxt.ast, copy default_name)
+        extract(ctxt.ast, default_name.clone())
     }
 }
 
@@ -61,7 +61,7 @@ fn top_moddoc_from_crate(
     default_name: ~str
 ) -> doc::ModDoc {
     moddoc_from_mod(mk_itemdoc(ast::crate_node_id, default_name),
-                    copy crate.node.module)
+                    crate.node.module.clone())
 }
 
 fn mk_itemdoc(id: ast::node_id, name: ~str) -> doc::ItemDoc {
@@ -84,7 +84,7 @@ fn moddoc_from_mod(
         item: itemdoc,
         items: do module_.items.iter().filter_map |item| {
             let ItemDoc = mk_itemdoc(item.id, to_str(item.ident));
-            match copy item.node {
+            match item.node.clone() {
               ast::item_mod(m) => {
                 Some(doc::ModTag(
                     moddoc_from_mod(ItemDoc, m)
@@ -107,7 +107,7 @@ fn moddoc_from_mod(
               }
               ast::item_enum(enum_definition, _) => {
                 Some(doc::EnumTag(
-                    enumdoc_from_enum(ItemDoc, copy enum_definition.variants)
+                    enumdoc_from_enum(ItemDoc, enum_definition.variants.clone())
                 ))
               }
               ast::item_trait(_, _, methods) => {
@@ -203,7 +203,7 @@ fn traitdoc_from_trait(
     doc::TraitDoc {
         item: itemdoc,
         methods: do methods.iter().transform |method| {
-            match copy *method {
+            match (*method).clone() {
               ast::required(ty_m) => {
                 doc::MethodDoc {
                     name: to_str(ty_m.ident),
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index 202177b5cfc..ad0dabdc3a4 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -154,7 +154,7 @@ pub fn default_par_fold<T:Clone>(ctxt: T) -> Fold<T> {
 pub fn default_seq_fold_doc<T>(fold: &Fold<T>, doc: doc::Doc) -> doc::Doc {
     doc::Doc {
         pages: do doc.pages.iter().transform |page| {
-            match copy *page {
+            match (*page).clone() {
               doc::CratePage(doc) => {
                 doc::CratePage((fold.fold_crate)(fold, doc))
               }
@@ -172,7 +172,7 @@ pub fn default_seq_fold_crate<T>(
     doc: doc::CrateDoc
 ) -> doc::CrateDoc {
     doc::CrateDoc {
-        topmod: (fold.fold_mod)(fold, copy doc.topmod)
+        topmod: (fold.fold_mod)(fold, doc.topmod.clone())
     }
 }
 
@@ -188,9 +188,9 @@ pub fn default_any_fold_mod<T:Clone>(
     doc: doc::ModDoc
 ) -> doc::ModDoc {
     doc::ModDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         items: doc.items.iter().transform(|ItemTag| {
-            fold_ItemTag(fold, copy *ItemTag)
+            fold_ItemTag(fold, (*ItemTag).clone())
         }).collect(),
         .. doc
     }
@@ -201,9 +201,9 @@ pub fn default_seq_fold_mod<T>(
     doc: doc::ModDoc
 ) -> doc::ModDoc {
     doc::ModDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         items: doc.items.iter().transform(|ItemTag| {
-            fold_ItemTag(fold, copy *ItemTag)
+            fold_ItemTag(fold, (*ItemTag).clone())
         }).collect(),
         .. doc
     }
@@ -214,9 +214,9 @@ pub fn default_par_fold_mod<T:Clone>(
     doc: doc::ModDoc
 ) -> doc::ModDoc {
     doc::ModDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         items: doc.items.iter().transform(|ItemTag| {
-            fold_ItemTag(fold, copy *ItemTag)
+            fold_ItemTag(fold, (*ItemTag).clone())
         }).collect(),
         .. doc
     }
@@ -227,9 +227,9 @@ pub fn default_any_fold_nmod<T:Clone>(
     doc: doc::NmodDoc
 ) -> doc::NmodDoc {
     doc::NmodDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         fns: doc.fns.iter().transform(|FnDoc| {
-            (fold.fold_fn)(fold, copy *FnDoc)
+            (fold.fold_fn)(fold, (*FnDoc).clone())
         }).collect(),
         .. doc
     }
@@ -240,9 +240,9 @@ pub fn default_seq_fold_nmod<T>(
     doc: doc::NmodDoc
 ) -> doc::NmodDoc {
     doc::NmodDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         fns: doc.fns.iter().transform(|FnDoc| {
-            (fold.fold_fn)(fold, copy *FnDoc)
+            (fold.fold_fn)(fold, (*FnDoc).clone())
         }).collect(),
         .. doc
     }
@@ -253,9 +253,9 @@ pub fn default_par_fold_nmod<T:Clone>(
     doc: doc::NmodDoc
 ) -> doc::NmodDoc {
     doc::NmodDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         fns: doc.fns.iter().transform(|FnDoc| {
-            (fold.fold_fn)(fold, copy *FnDoc)
+            (fold.fold_fn)(fold, (*FnDoc).clone())
         }).collect(),
         .. doc
     }
@@ -298,7 +298,7 @@ pub fn default_seq_fold_fn<T>(
     doc: doc::FnDoc
 ) -> doc::FnDoc {
     doc::SimpleItemDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
@@ -308,7 +308,7 @@ pub fn default_seq_fold_const<T>(
     doc: doc::ConstDoc
 ) -> doc::ConstDoc {
     doc::SimpleItemDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
@@ -318,7 +318,7 @@ pub fn default_seq_fold_enum<T>(
     doc: doc::EnumDoc
 ) -> doc::EnumDoc {
     doc::EnumDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
@@ -328,7 +328,7 @@ pub fn default_seq_fold_trait<T>(
     doc: doc::TraitDoc
 ) -> doc::TraitDoc {
     doc::TraitDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
@@ -338,7 +338,7 @@ pub fn default_seq_fold_impl<T>(
     doc: doc::ImplDoc
 ) -> doc::ImplDoc {
     doc::ImplDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
@@ -348,7 +348,7 @@ pub fn default_seq_fold_type<T>(
     doc: doc::TyDoc
 ) -> doc::TyDoc {
     doc::SimpleItemDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
@@ -358,7 +358,7 @@ pub fn default_seq_fold_struct<T>(
     doc: doc::StructDoc
 ) -> doc::StructDoc {
     doc::StructDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
@@ -369,7 +369,7 @@ fn default_fold_should_produce_same_doc() {
     let ast = parse::from_str(source);
     let doc = extract::extract(ast, ~"");
     let fld = default_seq_fold(());
-    let folded = (fld.fold_doc)(&fld, copy doc);
+    let folded = (fld.fold_doc)(&fld, doc.clone());
     assert_eq!(doc, folded);
 }
 
@@ -379,7 +379,7 @@ fn default_fold_should_produce_same_consts() {
     let ast = parse::from_str(source);
     let doc = extract::extract(ast, ~"");
     let fld = default_seq_fold(());
-    let folded = (fld.fold_doc)(&fld, copy doc);
+    let folded = (fld.fold_doc)(&fld, doc.clone());
     assert_eq!(doc, folded);
 }
 
@@ -389,7 +389,7 @@ fn default_fold_should_produce_same_enums() {
     let ast = parse::from_str(source);
     let doc = extract::extract(ast, ~"");
     let fld = default_seq_fold(());
-    let folded = (fld.fold_doc)(&fld, copy doc);
+    let folded = (fld.fold_doc)(&fld, doc.clone());
     assert_eq!(doc, folded);
 }
 
@@ -399,6 +399,6 @@ fn default_parallel_fold_should_produce_same_doc() {
     let ast = parse::from_str(source);
     let doc = extract::extract(ast, ~"");
     let fld = default_par_fold(());
-    let folded = (fld.fold_doc)(&fld, copy doc);
+    let folded = (fld.fold_doc)(&fld, doc.clone());
     assert_eq!(doc, folded);
 }
diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs
index 0c2ea5f1380..e766909b8ab 100644
--- a/src/librustdoc/markdown_index_pass.rs
+++ b/src/librustdoc/markdown_index_pass.rs
@@ -24,7 +24,7 @@ use pass::Pass;
 pub fn mk_pass(config: config::Config) -> Pass {
     Pass {
         name: ~"markdown_index",
-        f: |srv, doc| run(srv, doc, copy config)
+        f: |srv, doc| run(srv, doc, config.clone())
     }
 }
 
@@ -49,7 +49,7 @@ fn fold_mod(
     let doc = fold::default_any_fold_mod(fold, doc);
 
     doc::ModDoc {
-        index: Some(build_mod_index(copy doc, copy fold.ctxt)),
+        index: Some(build_mod_index(doc.clone(), fold.ctxt.clone())),
         .. doc
     }
 }
@@ -62,7 +62,7 @@ fn fold_nmod(
     let doc = fold::default_any_fold_nmod(fold, doc);
 
     doc::NmodDoc {
-        index: Some(build_nmod_index(copy doc, copy fold.ctxt)),
+        index: Some(build_nmod_index(doc.clone(), fold.ctxt.clone())),
         .. doc
     }
 }
@@ -73,7 +73,7 @@ fn build_mod_index(
 ) -> doc::Index {
     doc::Index {
         entries: doc.items.map(|doc| {
-            item_to_entry(copy *doc, &config)
+            item_to_entry((*doc).clone(), &config)
         })
     }
 }
@@ -84,7 +84,7 @@ fn build_nmod_index(
 ) -> doc::Index {
     doc::Index {
         entries: doc.fns.map(|doc| {
-            item_to_entry(doc::FnTag(copy *doc), &config)
+            item_to_entry(doc::FnTag((*doc).clone()), &config)
         })
     }
 }
@@ -97,16 +97,16 @@ fn item_to_entry(
       doc::ModTag(_) | doc::NmodTag(_)
       if config.output_style == config::DocPerMod => {
         markdown_writer::make_filename(config,
-                                       doc::ItemPage(copy doc)).to_str()
+                                       doc::ItemPage(doc.clone())).to_str()
       }
       _ => {
-        ~"#" + pandoc_header_id(markdown_pass::header_text(copy doc))
+        ~"#" + pandoc_header_id(markdown_pass::header_text(doc.clone()))
       }
     };
 
     doc::IndexEntry {
-        kind: markdown_pass::header_kind(copy doc),
-        name: markdown_pass::header_name(copy doc),
+        kind: markdown_pass::header_kind(doc.clone()),
+        name: markdown_pass::header_name(doc.clone()),
         brief: doc.brief(),
         link: link
     }
diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs
index f9ac8beb974..a1f4ddf986b 100644
--- a/src/librustdoc/markdown_pass.rs
+++ b/src/librustdoc/markdown_pass.rs
@@ -57,7 +57,7 @@ fn run(
     // makes the headers come out nested correctly.
     let sorted_doc = (sort_pass::mk_pass(
         ~"mods last", mods_last
-    ).f)(srv, copy doc);
+    ).f)(srv, doc.clone());
 
     write_markdown(sorted_doc, writer_factory);
 
@@ -77,15 +77,15 @@ pub fn write_markdown(
     // (See #2484, which is closed.)
     do doc.pages.map |page| {
         let ctxt = Ctxt {
-            w: writer_factory(copy *page)
+            w: writer_factory((*page).clone())
         };
         write_page(&ctxt, page)
     };
 }
 
 fn write_page(ctxt: &Ctxt, page: &doc::Page) {
-    write_title(ctxt, copy *page);
-    match copy *page {
+    write_title(ctxt, (*page).clone());
+    match (*page).clone() {
         doc::CratePage(doc) => {
             write_crate(ctxt, doc);
         }
@@ -106,7 +106,7 @@ fn write_title(ctxt: &Ctxt, page: doc::Page) {
 fn make_title(page: doc::Page) -> ~str {
     let item = match page {
         doc::CratePage(CrateDoc) => {
-            doc::ModTag(copy CrateDoc.topmod)
+            doc::ModTag(CrateDoc.topmod.clone())
         }
         doc::ItemPage(ItemTag) => {
             ItemTag
@@ -208,7 +208,7 @@ pub fn header_name(doc: doc::ItemTag) -> ~str {
 pub fn header_text(doc: doc::ItemTag) -> ~str {
     match &doc {
         &doc::ImplTag(ref ImplDoc) => {
-            let header_kind = header_kind(copy doc);
+            let header_kind = header_kind(doc.clone());
             let bounds = if ImplDoc.bounds_str.is_some() {
                 fmt!(" where `%s`", *ImplDoc.bounds_str.get_ref())
             } else {
@@ -227,7 +227,7 @@ pub fn header_text(doc: doc::ItemTag) -> ~str {
         _ => {}
     }
 
-    header_text_(header_kind(copy doc),
+    header_text_(header_kind(doc.clone()),
                  header_name(doc))
 }
 
@@ -239,7 +239,7 @@ fn write_crate(
     ctxt: &Ctxt,
     doc: doc::CrateDoc
 ) {
-    write_top_module(ctxt, copy doc.topmod);
+    write_top_module(ctxt, doc.topmod.clone());
 }
 
 fn write_top_module(
@@ -280,13 +280,13 @@ fn write_desc(
 
 fn write_sections(ctxt: &Ctxt, sections: &[doc::Section]) {
     for sections.iter().advance |section| {
-        write_section(ctxt, copy *section);
+        write_section(ctxt, (*section).clone());
     }
 }
 
 fn write_section(ctxt: &Ctxt, section: doc::Section) {
-    write_header_(ctxt, H4, copy section.header);
-    ctxt.w.put_line(copy section.body);
+    write_header_(ctxt, H4, section.header.clone());
+    ctxt.w.put_line(section.body.clone());
     ctxt.w.put_line(~"");
 }
 
@@ -300,7 +300,7 @@ fn write_mod_contents(
     }
 
     for doc.items.iter().advance |itemTag| {
-        write_item(ctxt, copy *itemTag);
+        write_item(ctxt, (*itemTag).clone());
     }
 }
 
@@ -314,7 +314,7 @@ fn write_item_no_header(ctxt: &Ctxt, doc: doc::ItemTag) {
 
 fn write_item_(ctxt: &Ctxt, doc: doc::ItemTag, write_header: bool) {
     if write_header {
-        write_item_header(ctxt, copy doc);
+        write_item_header(ctxt, doc.clone());
     }
 
     match doc {
@@ -351,7 +351,7 @@ fn write_index(ctxt: &Ctxt, index: &doc::Index) {
 
     for index.entries.iter().advance |entry| {
         let header = header_text_(entry.kind, entry.name);
-        let id = copy entry.link;
+        let id = entry.link.clone();
         if entry.brief.is_some() {
             ctxt.w.put_line(fmt!("* [%s](%s) - %s",
                                  header, id, *entry.brief.get_ref()));
@@ -371,8 +371,8 @@ fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) {
     }
 
     for doc.fns.iter().advance |FnDoc| {
-        write_item_header(ctxt, doc::FnTag(copy *FnDoc));
-        write_fn(ctxt, copy *FnDoc);
+        write_item_header(ctxt, doc::FnTag((*FnDoc).clone()));
+        write_fn(ctxt, (*FnDoc).clone());
     }
 }
 
@@ -380,12 +380,7 @@ fn write_fn(
     ctxt: &Ctxt,
     doc: doc::FnDoc
 ) {
-    write_fnlike(
-        ctxt,
-        copy doc.sig,
-        doc.desc(),
-        doc.sections()
-    );
+    write_fnlike(ctxt, doc.sig.clone(), doc.desc(), doc.sections());
 }
 
 fn write_fnlike(
@@ -418,7 +413,7 @@ fn write_const(
     ctxt: &Ctxt,
     doc: doc::ConstDoc
 ) {
-    write_sig(ctxt, copy doc.sig);
+    write_sig(ctxt, doc.sig.clone());
     write_common(ctxt, doc.desc(), doc.sections());
 }
 
@@ -441,7 +436,7 @@ fn write_variants(
     write_header_(ctxt, H4, ~"Variants");
 
     for docs.iter().advance |variant| {
-        write_variant(ctxt, copy *variant);
+        write_variant(ctxt, (*variant).clone());
     }
 
     ctxt.w.put_line(~"");
@@ -454,7 +449,7 @@ fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) {
     // space out list items so they all end up within paragraph elements
     ctxt.w.put_line(~"");
 
-    match copy doc.desc {
+    match doc.desc.clone() {
         Some(desc) => {
             ctxt.w.put_line(list_item_indent(fmt!("* `%s` - %s", *sig, desc)));
         }
@@ -480,18 +475,13 @@ fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) {
 
 fn write_methods(ctxt: &Ctxt, docs: &[doc::MethodDoc]) {
     for docs.iter().advance |doc| {
-        write_method(ctxt, copy *doc);
+        write_method(ctxt, (*doc).clone());
     }
 }
 
 fn write_method(ctxt: &Ctxt, doc: doc::MethodDoc) {
     write_header_(ctxt, H3, header_text_("Method", doc.name));
-    write_fnlike(
-        ctxt,
-        copy doc.sig,
-        copy doc.desc,
-        doc.sections
-    );
+    write_fnlike(ctxt, doc.sig.clone(), doc.desc.clone(), doc.sections);
 }
 
 fn write_impl(ctxt: &Ctxt, doc: doc::ImplDoc) {
@@ -503,7 +493,7 @@ fn write_type(
     ctxt: &Ctxt,
     doc: doc::TyDoc
 ) {
-    write_sig(ctxt, copy doc.sig);
+    write_sig(ctxt, doc.sig.clone());
     write_common(ctxt, doc.desc(), doc.sections());
 }
 
@@ -511,7 +501,7 @@ fn put_struct(
     ctxt: &Ctxt,
     doc: doc::StructDoc
 ) {
-    write_sig(ctxt, copy doc.sig);
+    write_sig(ctxt, doc.sig.clone());
     write_common(ctxt, doc.desc(), doc.sections());
 }
 
@@ -766,7 +756,7 @@ mod test {
                     topmod: doc::ModDoc{
                         items: ~[doc::FnTag(doc::SimpleItemDoc{
                             sig: Some(~"line 1\nline 2"),
-                            .. copy doc.cratemod().fns()[0]
+                            .. (doc.cratemod().fns()[0]).clone()
                         })],
                         .. doc.cratemod()
                     },
diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs
index 3dc9f1799a4..74ce1b650bc 100644
--- a/src/librustdoc/markdown_writer.rs
+++ b/src/librustdoc/markdown_writer.rs
@@ -22,6 +22,7 @@ use std::str;
 use std::task;
 use extra::future;
 
+#[deriving(Clone)]
 pub enum WriteInstr {
     Write(~str),
     Done
@@ -90,7 +91,7 @@ fn pandoc_writer(
     page: doc::Page
 ) -> Writer {
     assert!(config.pandoc_cmd.is_some());
-    let pandoc_cmd = copy *config.pandoc_cmd.get_ref();
+    let pandoc_cmd = (*config.pandoc_cmd.get_ref()).clone();
     let filename = make_local_filename(config, page);
 
     let pandoc_args = ~[
@@ -198,7 +199,7 @@ pub fn future_writer_factory(
             let mut future = future;
             writer_ch.send(writer);
             let s = future.get();
-            markdown_ch.send((copy page, s));
+            markdown_ch.send((page.clone(), s));
         }
         writer_po.recv()
     };
@@ -208,7 +209,7 @@ pub fn future_writer_factory(
 
 fn future_writer() -> (Writer, future::Future<~str>) {
     let (port, chan) = comm::stream();
-    let writer: ~fn(instr: WriteInstr) = |instr| chan.send(copy instr);
+    let writer: ~fn(instr: WriteInstr) = |instr| chan.send(instr.clone());
     let future = do future::from_fn || {
         let mut res = ~"";
         loop {
@@ -234,7 +235,7 @@ mod test {
 
     fn mk_doc(name: ~str, source: ~str) -> doc::Doc {
         do astsrv::from_str(source) |srv| {
-            let doc = extract::from_srv(srv.clone(), copy name);
+            let doc = extract::from_srv(srv.clone(), name.clone());
             let doc = (path_pass::mk_pass().f)(srv.clone(), doc);
             doc
         }
@@ -278,7 +279,7 @@ mod test {
         };
         let doc = mk_doc(~"", ~"mod a { mod b { } }");
         // hidden __std_macros module at the start.
-        let modb = copy doc.cratemod().mods()[1].mods()[0];
+        let modb = doc.cratemod().mods()[1].mods()[0].clone();
         let page = doc::ItemPage(doc::ModTag(modb));
         let filename = make_local_filename(&config, page);
         assert_eq!(filename, Path("output/dir/a_b.html"));
diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs
index 7abbc0e823a..4f1ce45cb60 100644
--- a/src/librustdoc/page_pass.rs
+++ b/src/librustdoc/page_pass.rs
@@ -23,7 +23,6 @@ use doc;
 use fold::Fold;
 use fold;
 use pass::Pass;
-use util::NominalOp;
 
 use std::comm::*;
 use std::task;
@@ -62,8 +61,6 @@ pub fn run(
 type PagePort = Port<Option<doc::Page>>;
 type PageChan = SharedChan<Option<doc::Page>>;
 
-type NominalPageChan = NominalOp<PageChan>;
-
 fn make_doc_from_pages(page_port: &PagePort) -> doc::Doc {
     let mut pages = ~[];
     loop {
@@ -81,46 +78,39 @@ fn make_doc_from_pages(page_port: &PagePort) -> doc::Doc {
 
 fn find_pages(doc: doc::Doc, page_chan: PageChan) {
     let fold = Fold {
-        ctxt: NominalOp { op: page_chan.clone() },
+        ctxt: page_chan.clone(),
         fold_crate: fold_crate,
         fold_mod: fold_mod,
         fold_nmod: fold_nmod,
-        .. fold::default_any_fold(NominalOp { op: page_chan.clone() })
+        .. fold::default_any_fold(page_chan.clone())
     };
-    (fold.fold_doc)(&fold, copy doc);
+    (fold.fold_doc)(&fold, doc.clone());
 
     page_chan.send(None);
 }
 
-fn fold_crate(
-    fold: &fold::Fold<NominalPageChan>,
-    doc: doc::CrateDoc
-) -> doc::CrateDoc {
-
+fn fold_crate(fold: &fold::Fold<PageChan>, doc: doc::CrateDoc)
+              -> doc::CrateDoc {
     let doc = fold::default_seq_fold_crate(fold, doc);
 
     let page = doc::CratePage(doc::CrateDoc {
-        topmod: strip_mod(copy doc.topmod),
-        .. copy doc
+        topmod: strip_mod(doc.topmod.clone()),
+        .. doc.clone()
     });
 
-    fold.ctxt.op.send(Some(page));
+    fold.ctxt.send(Some(page));
 
     doc
 }
 
-fn fold_mod(
-    fold: &fold::Fold<NominalPageChan>,
-    doc: doc::ModDoc
-) -> doc::ModDoc {
-
+fn fold_mod(fold: &fold::Fold<PageChan>, doc: doc::ModDoc) -> doc::ModDoc {
     let doc = fold::default_any_fold_mod(fold, doc);
 
     if doc.id() != ast::crate_node_id {
 
-        let doc = strip_mod(copy doc);
+        let doc = strip_mod(doc.clone());
         let page = doc::ItemPage(doc::ModTag(doc));
-        fold.ctxt.op.send(Some(page));
+        fold.ctxt.send(Some(page));
     }
 
     doc
@@ -133,18 +123,15 @@ fn strip_mod(doc: doc::ModDoc) -> doc::ModDoc {
               doc::ModTag(_) | doc::NmodTag(_) => false,
               _ => true
             }
-        }.transform(|x| copy *x).collect::<~[doc::ItemTag]>(),
-        .. copy doc
+        }.transform(|x| (*x).clone()).collect::<~[doc::ItemTag]>(),
+        .. doc.clone()
     }
 }
 
-fn fold_nmod(
-    fold: &fold::Fold<NominalPageChan>,
-    doc: doc::NmodDoc
-) -> doc::NmodDoc {
+fn fold_nmod(fold: &fold::Fold<PageChan>, doc: doc::NmodDoc) -> doc::NmodDoc {
     let doc = fold::default_seq_fold_nmod(fold, doc);
-    let page = doc::ItemPage(doc::NmodTag(copy doc));
-    fold.ctxt.op.send(Some(page));
+    let page = doc::ItemPage(doc::NmodTag(doc.clone()));
+    fold.ctxt.send(Some(page));
     return doc;
 }
 
@@ -162,7 +149,7 @@ mod test {
         output_style: config::OutputStyle,
         source: ~str
     ) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             let doc = (attr_pass::mk_pass().f)(srv.clone(), doc);
             let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc);
@@ -171,7 +158,7 @@ mod test {
     }
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        mk_doc_(config::DocPerMod, copy source)
+        mk_doc_(config::DocPerMod, source.clone())
     }
 
     #[test]
diff --git a/src/librustdoc/parse.rs b/src/librustdoc/parse.rs
index bf782c9d5f3..83aa6e46c76 100644
--- a/src/librustdoc/parse.rs
+++ b/src/librustdoc/parse.rs
@@ -29,7 +29,7 @@ pub fn from_str(source: @str) -> @ast::crate {
 
 pub fn from_file_sess(sess: session::Session, file: &Path) -> @ast::crate {
     parse::parse_crate_from_file(
-        file, cfg(sess, file_input(copy *file)), sess.parse_sess)
+        file, cfg(sess, file_input((*file).clone())), sess.parse_sess)
 }
 
 pub fn from_str_sess(sess: session::Session, source: @str) -> @ast::crate {
diff --git a/src/librustdoc/pass.rs b/src/librustdoc/pass.rs
index 3497e9515c6..0654e1bbd1a 100644
--- a/src/librustdoc/pass.rs
+++ b/src/librustdoc/pass.rs
@@ -31,8 +31,8 @@ pub fn run_passes(
     do passes.iter().fold(doc) |doc, pass| {
         debug!("pass #%d", passno);
         passno += 1;
-        do time(copy pass.name) {
-            (pass.f)(srv.clone(), copy doc)
+        do time(pass.name.clone()) {
+            (pass.f)(srv.clone(), doc.clone())
         }
     }
 }
@@ -49,7 +49,7 @@ fn test_run_passes() {
                     topmod: doc::ModDoc{
                         item: doc::ItemDoc {
                             name: doc.cratemod().name() + "two",
-                            .. copy doc.cratemod().item
+                            .. doc.cratemod().item.clone()
                         },
                         items: ~[],
                         index: None
@@ -68,7 +68,7 @@ fn test_run_passes() {
                     topmod: doc::ModDoc{
                         item: doc::ItemDoc {
                             name: doc.cratemod().name() + "three",
-                            .. copy doc.cratemod().item
+                            .. doc.cratemod().item.clone()
                         },
                         items: ~[],
                         index: None
diff --git a/src/librustdoc/path_pass.rs b/src/librustdoc/path_pass.rs
index d26c3f8da6e..b333417f2f8 100644
--- a/src/librustdoc/path_pass.rs
+++ b/src/librustdoc/path_pass.rs
@@ -38,7 +38,7 @@ impl Clone for Ctxt {
     fn clone(&self) -> Ctxt {
         Ctxt {
             srv: self.srv.clone(),
-            path: @mut copy *self.path
+            path: @mut (*self.path).clone()
         }
     }
 }
@@ -61,7 +61,7 @@ fn run(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
 
 fn fold_item(fold: &fold::Fold<Ctxt>, doc: doc::ItemDoc) -> doc::ItemDoc {
     doc::ItemDoc {
-        path: copy *fold.ctxt.path,
+        path: (*fold.ctxt.path).clone(),
         .. doc
     }
 }
@@ -75,7 +75,7 @@ fn fold_mod(fold: &fold::Fold<Ctxt>, doc: doc::ModDoc) -> doc::ModDoc {
     if !is_topmod { fold.ctxt.path.pop(); }
 
     doc::ModDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
@@ -86,7 +86,7 @@ fn fold_nmod(fold: &fold::Fold<Ctxt>, doc: doc::NmodDoc) -> doc::NmodDoc {
     fold.ctxt.path.pop();
 
     doc::NmodDoc {
-        item: (fold.fold_item)(fold, copy doc.item),
+        item: (fold.fold_item)(fold, doc.item.clone()),
         .. doc
     }
 }
diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs
index 96c5df10680..04cb0e3f710 100644
--- a/src/librustdoc/prune_hidden_pass.rs
+++ b/src/librustdoc/prune_hidden_pass.rs
@@ -43,7 +43,7 @@ fn fold_mod(
     doc::ModDoc {
         items: do doc.items.iter().filter |item_tag| {
             !is_hidden(fold.ctxt.clone(), item_tag.item())
-        }.transform(|x| copy *x).collect(),
+        }.transform(|x| (*x).clone()).collect(),
         .. doc
     }
 }
@@ -54,7 +54,7 @@ fn is_hidden(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool {
     let id = doc.id;
     do astsrv::exec(srv) |ctxt| {
         let attrs = match ctxt.ast_map.get_copy(&id) {
-          ast_map::node_item(item, _) => copy item.attrs,
+          ast_map::node_item(item, _) => item.attrs.clone(),
           _ => ~[]
         };
         attr_parser::parse_hidden(attrs)
@@ -69,7 +69,7 @@ mod test {
     use prune_hidden_pass::run;
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             run(srv.clone(), doc)
         }
diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs
index aeb6e02f244..6f3f91f3c65 100644
--- a/src/librustdoc/prune_private_pass.rs
+++ b/src/librustdoc/prune_private_pass.rs
@@ -61,11 +61,11 @@ fn fold_impl(
                 match item.node {
                     ast::item_impl(_, None, _, ref methods) => {
                         // Associated impls have complex rules for method visibility
-                        strip_priv_methods(copy doc, *methods, item.vis)
+                        strip_priv_methods(doc.clone(), *methods, item.vis)
                     }
                     ast::item_impl(_, Some(_), _ ,_) => {
                         // Trait impls don't
-                        copy doc
+                        doc.clone()
                     }
                     _ => fail!()
                 }
@@ -91,7 +91,7 @@ fn strip_priv_methods(
             ast::private => false,
             ast::inherited => item_vis == ast::public
         }
-    }.transform(|x| copy *x).collect();
+    }.transform(|x| (*x).clone()).collect();
 
     doc::ImplDoc {
         methods: methods,
@@ -126,7 +126,7 @@ fn fold_mod(
                     is_visible(fold.ctxt.clone(), item_tag.item())
                 }
             }
-        }).transform(|x| copy *x).collect(),
+        }).transform(|x| (*x).clone()).collect(),
         .. doc
     }
 }
@@ -163,7 +163,7 @@ mod test {
     use prune_private_pass::run;
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             let doc = tystr_pass::run(srv.clone(), doc);
             run(srv.clone(), doc)
diff --git a/src/librustdoc/rustdoc.rs b/src/librustdoc/rustdoc.rs
index d12f85dcc44..644f3d78cf4 100644
--- a/src/librustdoc/rustdoc.rs
+++ b/src/librustdoc/rustdoc.rs
@@ -59,7 +59,6 @@ pub mod page_pass;
 pub mod sectionalize_pass;
 pub mod escape_pass;
 pub mod prune_private_pass;
-pub mod util;
 
 pub fn main() {
     let args = os::args();
@@ -83,7 +82,7 @@ pub fn main() {
 /// Runs rustdoc over the given file
 fn run(config: Config) {
 
-    let source_file = copy config.input_crate;
+    let source_file = config.input_crate.clone();
 
     // Create an AST service from the source code
     do astsrv::from_file(source_file.to_str()) |srv| {
@@ -96,7 +95,7 @@ fn run(config: Config) {
         // Extract the initial doc tree from the AST. This contains
         // just names and node ids.
         let doc = time(~"extract", || {
-            let default_name = copy source_file;
+            let default_name = source_file.clone();
             extract::from_srv(srv.clone(), default_name.to_str())
         });
 
@@ -127,13 +126,13 @@ fn run(config: Config) {
             // Sort items again by kind
             sort_item_type_pass::mk_pass(),
             // Create indexes appropriate for markdown
-            markdown_index_pass::mk_pass(copy config),
+            markdown_index_pass::mk_pass(config.clone()),
             // Break the document into pages if required by the
             // output format
             page_pass::mk_pass(config.output_style),
             // Render
             markdown_pass::mk_pass(
-                markdown_writer::make_writer_factory(copy config)
+                markdown_writer::make_writer_factory(config.clone())
             )
         ]);
     }
diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs
index 9b7374eb71c..9f39f854539 100644
--- a/src/librustdoc/sectionalize_pass.rs
+++ b/src/librustdoc/sectionalize_pass.rs
@@ -39,7 +39,7 @@ pub fn run(_srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
 
 fn fold_item(fold: &fold::Fold<()>, doc: doc::ItemDoc) -> doc::ItemDoc {
     let doc = fold::default_seq_fold_item(fold, doc);
-    let (desc, sections) = sectionalize(copy doc.desc);
+    let (desc, sections) = sectionalize(doc.desc.clone());
 
     doc::ItemDoc {
         desc: desc,
@@ -53,12 +53,12 @@ fn fold_trait(fold: &fold::Fold<()>, doc: doc::TraitDoc) -> doc::TraitDoc {
 
     doc::TraitDoc {
         methods: do doc.methods.map |method| {
-            let (desc, sections) = sectionalize(copy method.desc);
+            let (desc, sections) = sectionalize(method.desc.clone());
 
             doc::MethodDoc {
                 desc: desc,
                 sections: sections,
-                .. copy *method
+                .. (*method).clone()
             }
         },
         .. doc
@@ -70,12 +70,12 @@ fn fold_impl(fold: &fold::Fold<()>, doc: doc::ImplDoc) -> doc::ImplDoc {
 
     doc::ImplDoc {
         methods: do doc.methods.map |method| {
-            let (desc, sections) = sectionalize(copy method.desc);
+            let (desc, sections) = sectionalize(method.desc.clone());
 
             doc::MethodDoc {
                 desc: desc,
                 sections: sections,
-                .. copy *method
+                .. (*method).clone()
             }
         },
         .. doc
@@ -105,14 +105,14 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) {
     }
 
     let mut new_desc = None::<~str>;
-    let mut current_section = None;
+    let mut current_section: Option<doc::Section> = None;
     let mut sections = ~[];
 
     for desc.get_ref().any_line_iter().advance |line| {
         match parse_header(line) {
           Some(header) => {
             if current_section.is_some() {
-                sections.push(copy *current_section.get_ref());
+                sections.push((*current_section.get_ref()).clone());
             }
             current_section = Some(doc::Section {
                 header: header.to_owned(),
@@ -120,7 +120,7 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) {
             });
           }
           None => {
-            match copy current_section {
+            match current_section.clone() {
               Some(section) => {
                 current_section = Some(doc::Section {
                     body: fmt!("%s\n%s", section.body, line),
@@ -128,7 +128,7 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) {
                 });
               }
               None => {
-                new_desc = match copy new_desc {
+                new_desc = match new_desc.clone() {
                   Some(desc) => {
                     Some(fmt!("%s\n%s", desc, line))
                   }
@@ -170,7 +170,7 @@ mod test {
     use sectionalize_pass::run;
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             let doc = (attr_pass::mk_pass().f)(srv.clone(), doc);
             let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc);
diff --git a/src/librustdoc/sort_pass.rs b/src/librustdoc/sort_pass.rs
index 9b125f16afe..8b973c78d73 100644
--- a/src/librustdoc/sort_pass.rs
+++ b/src/librustdoc/sort_pass.rs
@@ -15,20 +15,30 @@ use doc;
 use fold::Fold;
 use fold;
 use pass::Pass;
-use util::NominalOp;
 
 #[cfg(test)] use extract;
 
 use extra::sort;
+use std::clone::Clone;
 
 pub type ItemLtEqOp = @fn(v1: &doc::ItemTag, v2:  &doc::ItemTag) -> bool;
 
-type ItemLtEq = NominalOp<ItemLtEqOp>;
+struct ItemLtEq {
+    op: ItemLtEqOp,
+}
+
+impl Clone for ItemLtEq {
+    fn clone(&self) -> ItemLtEq {
+        ItemLtEq {
+            op: self.op,
+        }
+    }
+}
 
 pub fn mk_pass(name: ~str, lteq: ItemLtEqOp) -> Pass {
     Pass {
-        name: copy name,
-        f: |srv, doc| run(srv, doc, NominalOp { op: lteq })
+        name: name.clone(),
+        f: |srv, doc| run(srv, doc, ItemLtEq { op: lteq })
     }
 }
 
diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs
index 453c40af915..5121a312d93 100644
--- a/src/librustdoc/text_pass.rs
+++ b/src/librustdoc/text_pass.rs
@@ -17,14 +17,13 @@ use doc;
 use fold::Fold;
 use fold;
 use pass::Pass;
-use util::NominalOp;
 
 use std::cell::Cell;
 
 pub fn mk_pass(name: ~str, op: @fn(&str) -> ~str) -> Pass {
     let op = Cell::new(op);
     Pass {
-        name: copy name,
+        name: name.clone(),
         f: |srv: astsrv::Srv, doc: doc::Doc| -> doc::Doc {
             run(srv, doc, op.take())
         }
@@ -33,13 +32,25 @@ pub fn mk_pass(name: ~str, op: @fn(&str) -> ~str) -> Pass {
 
 type Op = @fn(&str) -> ~str;
 
+struct WrappedOp {
+    op: Op,
+}
+
+impl Clone for WrappedOp {
+    fn clone(&self) -> WrappedOp {
+        WrappedOp {
+            op: self.op,
+        }
+    }
+}
+
 #[allow(non_implicitly_copyable_typarams)]
 fn run(
     _srv: astsrv::Srv,
     doc: doc::Doc,
     op: Op
 ) -> doc::Doc {
-    let op = NominalOp {
+    let op = WrappedOp {
         op: op
     };
     let fold = Fold {
@@ -52,37 +63,32 @@ fn run(
     (fold.fold_doc)(&fold, doc)
 }
 
-fn maybe_apply_op(op: NominalOp<Op>, s: &Option<~str>) -> Option<~str> {
+fn maybe_apply_op(op: WrappedOp, s: &Option<~str>) -> Option<~str> {
     s.map(|s| (op.op)(*s) )
 }
 
-fn fold_item(
-    fold: &fold::Fold<NominalOp<Op>>,
-    doc: doc::ItemDoc
-) -> doc::ItemDoc {
+fn fold_item(fold: &fold::Fold<WrappedOp>, doc: doc::ItemDoc)
+             -> doc::ItemDoc {
     let doc = fold::default_seq_fold_item(fold, doc);
 
     doc::ItemDoc {
         brief: maybe_apply_op(fold.ctxt, &doc.brief),
         desc: maybe_apply_op(fold.ctxt, &doc.desc),
-        sections: apply_to_sections(fold.ctxt, copy doc.sections),
+        sections: apply_to_sections(fold.ctxt, doc.sections.clone()),
         .. doc
     }
 }
 
-fn apply_to_sections(
-    op: NominalOp<Op>,
-    sections: ~[doc::Section]
-) -> ~[doc::Section] {
+fn apply_to_sections(op: WrappedOp, sections: ~[doc::Section])
+                     -> ~[doc::Section] {
     sections.map(|section| doc::Section {
-        header: (op.op)(copy section.header),
-        body: (op.op)(copy section.body)
+        header: (op.op)(section.header.clone()),
+        body: (op.op)(section.body.clone())
     })
 }
 
-fn fold_enum(
-    fold: &fold::Fold<NominalOp<Op>>,
-    doc: doc::EnumDoc) -> doc::EnumDoc {
+fn fold_enum(fold: &fold::Fold<WrappedOp>, doc: doc::EnumDoc)
+             -> doc::EnumDoc {
     let doc = fold::default_seq_fold_enum(fold, doc);
     let fold_copy = *fold;
 
@@ -90,47 +96,41 @@ fn fold_enum(
         variants: do doc.variants.map |variant| {
             doc::VariantDoc {
                 desc: maybe_apply_op(fold_copy.ctxt, &variant.desc),
-                .. copy *variant
+                .. (*variant).clone()
             }
         },
         .. doc
     }
 }
 
-fn fold_trait(
-    fold: &fold::Fold<NominalOp<Op>>,
-    doc: doc::TraitDoc
-) -> doc::TraitDoc {
+fn fold_trait(fold: &fold::Fold<WrappedOp>, doc: doc::TraitDoc)
+              -> doc::TraitDoc {
     let doc = fold::default_seq_fold_trait(fold, doc);
 
     doc::TraitDoc {
-        methods: apply_to_methods(fold.ctxt, copy doc.methods),
+        methods: apply_to_methods(fold.ctxt, doc.methods.clone()),
         .. doc
     }
 }
 
-fn apply_to_methods(
-    op: NominalOp<Op>,
-    docs: ~[doc::MethodDoc]
-) -> ~[doc::MethodDoc] {
+fn apply_to_methods(op: WrappedOp, docs: ~[doc::MethodDoc])
+                    -> ~[doc::MethodDoc] {
     do docs.map |doc| {
         doc::MethodDoc {
             brief: maybe_apply_op(op, &doc.brief),
             desc: maybe_apply_op(op, &doc.desc),
-            sections: apply_to_sections(op, copy doc.sections),
-            .. copy *doc
+            sections: apply_to_sections(op, doc.sections.clone()),
+            .. (*doc).clone()
         }
     }
 }
 
-fn fold_impl(
-    fold: &fold::Fold<NominalOp<Op>>,
-    doc: doc::ImplDoc
-) -> doc::ImplDoc {
+fn fold_impl(fold: &fold::Fold<WrappedOp>, doc: doc::ImplDoc)
+             -> doc::ImplDoc {
     let doc = fold::default_seq_fold_impl(fold, doc);
 
     doc::ImplDoc {
-        methods: apply_to_methods(fold.ctxt, copy doc.methods),
+        methods: apply_to_methods(fold.ctxt, doc.methods.clone()),
         .. doc
     }
 }
@@ -147,7 +147,7 @@ mod test {
     use text_pass::mk_pass;
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             let doc = (attr_pass::mk_pass().f)(srv.clone(), doc);
             let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc);
diff --git a/src/librustdoc/trim_pass.rs b/src/librustdoc/trim_pass.rs
index 0d284fb48e2..aaba0427b62 100644
--- a/src/librustdoc/trim_pass.rs
+++ b/src/librustdoc/trim_pass.rs
@@ -32,7 +32,7 @@ mod test {
     use trim_pass::mk_pass;
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             let doc = (attr_pass::mk_pass().f)(srv.clone(), doc);
             let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc);
diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs
index 40c662e3a09..f66aeca06ff 100644
--- a/src/librustdoc/tystr_pass.rs
+++ b/src/librustdoc/tystr_pass.rs
@@ -90,7 +90,7 @@ fn fold_const(
 
     doc::SimpleItemDoc {
         sig: Some({
-            let doc = copy doc;
+            let doc = doc.clone();
             do astsrv::exec(srv) |ctxt| {
                 match ctxt.ast_map.get_copy(&doc.id()) {
                     ast_map::node_item(@ast::item {
@@ -115,16 +115,16 @@ fn fold_enum(
     doc::EnumDoc {
         variants: do doc.variants.iter().transform |variant| {
             let sig = {
-                let variant = copy *variant;
+                let variant = (*variant).clone();
                 do astsrv::exec(srv.clone()) |ctxt| {
                     match ctxt.ast_map.get_copy(&doc_id) {
                         ast_map::node_item(@ast::item {
                             node: ast::item_enum(ref enum_definition, _), _
                         }, _) => {
                             let ast_variant =
-                                copy *do enum_definition.variants.iter().find_ |v| {
+                                (*do enum_definition.variants.iter().find_ |v| {
                                 to_str(v.node.name) == variant.name
-                            }.get();
+                            }.get()).clone();
 
                             pprust::variant_to_str(
                                 &ast_variant, extract::interner())
@@ -136,7 +136,7 @@ fn fold_enum(
 
             doc::VariantDoc {
                 sig: Some(sig),
-                .. copy *variant
+                .. (*variant).clone()
             }
         }.collect(),
         .. doc
@@ -148,7 +148,7 @@ fn fold_trait(
     doc: doc::TraitDoc
 ) -> doc::TraitDoc {
     doc::TraitDoc {
-        methods: merge_methods(fold.ctxt.clone(), doc.id(), copy doc.methods),
+        methods: merge_methods(fold.ctxt.clone(), doc.id(), doc.methods.clone()),
         .. doc
     }
 }
@@ -160,8 +160,8 @@ fn merge_methods(
 ) -> ~[doc::MethodDoc] {
     do docs.iter().transform |doc| {
         doc::MethodDoc {
-            sig: get_method_sig(srv.clone(), item_id, copy doc.name),
-            .. copy *doc
+            sig: get_method_sig(srv.clone(), item_id, doc.name.clone()),
+            .. (*doc).clone()
         }
     }.collect()
 }
@@ -177,13 +177,13 @@ fn get_method_sig(
                 node: ast::item_trait(_, _, ref methods), _
             }, _) => {
                 match methods.iter().find_(|&method| {
-                    match copy *method {
+                    match (*method).clone() {
                         ast::required(ty_m) => to_str(ty_m.ident) == method_name,
                         ast::provided(m) => to_str(m.ident) == method_name,
                     }
                 }) {
                     Some(method) => {
-                        match copy *method {
+                        match (*method).clone() {
                             ast::required(ty_m) => {
                                 Some(pprust::fun_to_str(
                                     &ty_m.decl,
@@ -241,7 +241,7 @@ fn fold_impl(
     let srv = fold.ctxt.clone();
 
     let (bounds, trait_types, self_ty) = {
-        let doc = copy doc;
+        let doc = doc.clone();
         do astsrv::exec(srv) |ctxt| {
             match ctxt.ast_map.get_copy(&doc.id()) {
                 ast_map::node_item(@ast::item {
@@ -266,7 +266,7 @@ fn fold_impl(
         bounds_str: bounds,
         trait_types: trait_types,
         self_ty: self_ty,
-        methods: merge_methods(fold.ctxt.clone(), doc.id(), copy doc.methods),
+        methods: merge_methods(fold.ctxt.clone(), doc.id(), doc.methods.clone()),
         .. doc
     }
 }
@@ -280,7 +280,7 @@ fn fold_type(
 
     doc::SimpleItemDoc {
         sig: {
-            let doc = copy doc;
+            let doc = doc.clone();
             do astsrv::exec(srv) |ctxt| {
                 match ctxt.ast_map.get_copy(&doc.id()) {
                     ast_map::node_item(@ast::item {
@@ -311,7 +311,7 @@ fn fold_struct(
 
     doc::StructDoc {
         sig: {
-            let doc = copy doc;
+            let doc = doc.clone();
             do astsrv::exec(srv) |ctxt| {
                 match ctxt.ast_map.get_copy(&doc.id()) {
                     ast_map::node_item(item, _) => {
@@ -332,7 +332,7 @@ fn fold_struct(
 /// should be a simple pprust::struct_to_str function that does
 /// what I actually want
 fn strip_struct_extra_stuff(item: @ast::item) -> @ast::item {
-    let node = match copy item.node {
+    let node = match item.node.clone() {
         ast::item_struct(def, tys) => ast::item_struct(def, tys),
         _ => fail!("not a struct")
     };
@@ -340,7 +340,7 @@ fn strip_struct_extra_stuff(item: @ast::item) -> @ast::item {
     @ast::item {
         attrs: ~[], // Remove the attributes
         node: node,
-        .. copy *item
+        .. (*item).clone()
     }
 }
 
@@ -353,7 +353,7 @@ mod test {
     use tystr_pass::run;
 
     fn mk_doc(source: ~str) -> doc::Doc {
-        do astsrv::from_str(copy source) |srv| {
+        do astsrv::from_str(source.clone()) |srv| {
             let doc = extract::from_srv(srv.clone(), ~"");
             run(srv.clone(), doc)
         }
diff --git a/src/librustdoc/util.rs b/src/librustdoc/util.rs
deleted file mode 100644
index 20e64087442..00000000000
--- a/src/librustdoc/util.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-// Just a named container for our op, so it can have impls
-pub struct NominalOp<T> {
-    op: T
-}
-
-impl<T:Copy> Clone for NominalOp<T> {
-    fn clone(&self) -> NominalOp<T> { copy *self }
-}
diff --git a/src/librusti/program.rs b/src/librusti/program.rs
index f8cbd70c0b1..e3a32801ca9 100644
--- a/src/librusti/program.rs
+++ b/src/librusti/program.rs
@@ -22,6 +22,7 @@ use utils::*;
 
 /// This structure keeps track of the state of the world for the code being
 /// executed in rusti.
+#[deriving(Clone)]
 struct Program {
     /// All known local variables
     local_vars: HashMap<~str, LocalVariable>,
@@ -41,6 +42,7 @@ struct Program {
 }
 
 /// Represents a local variable that the program is currently using.
+#[deriving(Clone)]
 struct LocalVariable {
     /// Should this variable be locally declared as mutable?
     mutable: bool,
@@ -218,7 +220,7 @@ impl Program {
     pub fn set_cache(&self) {
         let map = @mut HashMap::new();
         for self.local_vars.iter().advance |(name, value)| {
-            map.insert(copy *name, @copy value.data);
+            map.insert((*name).clone(), @(value.data).clone());
         }
         local_data::set(tls_key, map);
     }
@@ -230,7 +232,7 @@ impl Program {
         let map = local_data::pop(tls_key).expect("tls is empty");
         do map.consume |name, value| {
             match self.local_vars.find_mut(&name) {
-                Some(v) => { v.data = copy *value; }
+                Some(v) => { v.data = (*value).clone(); }
                 None => { fail!("unknown variable %s", name) }
             }
         }
@@ -303,7 +305,7 @@ impl Program {
                         ty::ty_evec(mt, ty::vstore_slice(*)) |
                         ty::ty_evec(mt, ty::vstore_fixed(*)) => {
                             let vty = ppaux::ty_to_str(tcx, mt.ty);
-                            let derefs = copy tystr;
+                            let derefs = tystr.clone();
                             lvar.ty = tystr + "~[" + vty + "]";
                             lvar.alterations = Some((tystr + "&[" + vty + "]",
                                                      derefs));
@@ -312,7 +314,7 @@ impl Program {
                         // Similar to vectors, &str serializes to ~str, so a
                         // borrow must be taken
                         ty::ty_estr(ty::vstore_slice(*)) => {
-                            let derefs = copy tystr;
+                            let derefs = tystr.clone();
                             lvar.ty = tystr + "~str";
                             lvar.alterations = Some((tystr + "&str", derefs));
                             break;
@@ -326,7 +328,7 @@ impl Program {
                         // If we're just borrowing (no vectors or strings), then
                         // we just need to record how many borrows there were.
                         _ => {
-                            let derefs = copy tystr;
+                            let derefs = tystr.clone();
                             let tmptystr = ppaux::ty_to_str(tcx, t);
                             lvar.alterations = Some((tystr + tmptystr, derefs));
                             lvar.ty = tmptystr;
diff --git a/src/librusti/rusti.rs b/src/librusti/rusti.rs
index ab6ae0385fb..1bee2146089 100644
--- a/src/librusti/rusti.rs
+++ b/src/librusti/rusti.rs
@@ -118,7 +118,7 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
         binary: binary,
         addl_lib_search_paths: @mut lib_search_paths.map(|p| Path(*p)),
         jit: true,
-        .. copy *session::basic_options()
+        .. (*session::basic_options()).clone()
     };
     // Because we assume that everything is encodable (and assert so), add some
     // extra helpful information if the error crops up. Otherwise people are
@@ -224,7 +224,7 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
     let dinput = driver::str_input(test.to_managed());
     let cfg = driver::build_configuration(sess, binary, &dinput);
     let outputs = driver::build_output_filenames(&dinput, &None, &None, [], sess);
-    let (crate, tcx) = driver::compile_upto(sess, copy cfg, &dinput,
+    let (crate, tcx) = driver::compile_upto(sess, cfg.clone(), &dinput,
                                             driver::cu_typeck, Some(outputs));
     // Once we're typechecked, record the types of all local variables defined
     // in this input
@@ -300,9 +300,9 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
         let options = @session::options {
             binary: binary,
             addl_lib_search_paths: @mut ~[os::getcwd()],
-            .. copy *session::basic_options()
+            .. (*session::basic_options()).clone()
         };
-        let input = driver::file_input(copy src_path);
+        let input = driver::file_input(src_path.clone());
         let sess = driver::build_session(options, diagnostic::emit);
         *sess.building_library = true;
         let cfg = driver::build_configuration(sess, binary, &input);
@@ -393,11 +393,11 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer,
             for args.iter().advance |arg| {
                 let (crate, filename) =
                     if arg.ends_with(".rs") || arg.ends_with(".rc") {
-                    (arg.slice_to(arg.len() - 3).to_owned(), copy *arg)
+                    (arg.slice_to(arg.len() - 3).to_owned(), (*arg).clone())
                 } else {
-                    (copy *arg, *arg + ".rs")
+                    ((*arg).clone(), *arg + ".rs")
                 };
-                match compile_crate(filename, copy repl.binary) {
+                match compile_crate(filename, repl.binary.clone()) {
                     Some(_) => loaded_crates.push(crate),
                     None => { }
                 }
@@ -452,7 +452,7 @@ pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
         let len = split.len();
 
         if len > 0 {
-            let cmd = copy split[0];
+            let cmd = split[0].clone();
 
             if !cmd.is_empty() {
                 let args = if len > 1 {
@@ -473,9 +473,9 @@ pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
     }
 
     let line = Cell::new(line);
-    let program = Cell::new(copy repl.program);
-    let lib_search_paths = Cell::new(copy repl.lib_search_paths);
-    let binary = Cell::new(copy repl.binary);
+    let program = Cell::new(repl.program.clone());
+    let lib_search_paths = Cell::new(repl.lib_search_paths.clone());
+    let binary = Cell::new(repl.binary.clone());
     let result = do task::try {
         run(program.take(), binary.take(), lib_search_paths.take(), line.take())
     };
@@ -499,7 +499,7 @@ pub fn main() {
     let out = io::stdout();
     let mut repl = Repl {
         prompt: ~"rusti> ",
-        binary: copy args[0],
+        binary: args[0].clone(),
         running: true,
         lib_search_paths: ~[],
         engines: ~[],
diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs
index 17cb3521eb7..bcda135cbb6 100644
--- a/src/librustpkg/api.rs
+++ b/src/librustpkg/api.rs
@@ -66,9 +66,9 @@ pub fn install_lib(sysroot: @Path,
     let build_dir = workspace.push("build");
     let dst_dir = build_dir.push_rel(&*pkg_id.local_path);
     let pkg_src = PkgSrc {
-        root: copy workspace,
-        dst_dir: copy dst_dir,
-        id: copy pkg_id,
+        root: workspace.clone(),
+        dst_dir: dst_dir.clone(),
+        id: pkg_id.clone(),
         libs: ~[mk_crate(lib_path)],
         mains: ~[],
         tests: ~[],
diff --git a/src/librustpkg/crate.rs b/src/librustpkg/crate.rs
index 5fe45126032..f75c5347d71 100644
--- a/src/librustpkg/crate.rs
+++ b/src/librustpkg/crate.rs
@@ -12,6 +12,7 @@ use std::path::Path;
 use std::vec;
 
 /// A crate is a unit of Rust code to be compiled into a binary or library
+#[deriving(Clone)]
 pub struct Crate {
     file: Path,
     flags: ~[~str],
@@ -22,7 +23,7 @@ impl Crate {
 
     pub fn new(p: &Path) -> Crate {
         Crate {
-            file: copy *p,
+            file: (*p).clone(),
             flags: ~[],
             cfgs: ~[]
         }
@@ -30,29 +31,29 @@ impl Crate {
 
     fn flag(&self, flag: ~str) -> Crate {
         Crate {
-            flags: vec::append(copy self.flags, [flag]),
-            .. copy *self
+            flags: vec::append(self.flags.clone(), [flag]),
+            .. (*self).clone()
         }
     }
 
     fn flags(&self, flags: ~[~str]) -> Crate {
         Crate {
-            flags: vec::append(copy self.flags, flags),
-            .. copy *self
+            flags: vec::append(self.flags.clone(), flags),
+            .. (*self).clone()
         }
     }
 
     fn cfg(&self, cfg: ~str) -> Crate {
         Crate {
-            cfgs: vec::append(copy self.cfgs, [cfg]),
-            .. copy *self
+            cfgs: vec::append(self.cfgs.clone(), [cfg]),
+            .. (*self).clone()
         }
     }
 
     fn cfgs(&self, cfgs: ~[~str]) -> Crate {
         Crate {
-            cfgs: vec::append(copy self.cfgs, cfgs),
-            .. copy *self
+            cfgs: vec::append(self.cfgs.clone(), cfgs),
+            .. (*self).clone()
         }
     }
 }
diff --git a/src/librustpkg/package_id.rs b/src/librustpkg/package_id.rs
index d1000f7f845..e1cf5b1fd35 100644
--- a/src/librustpkg/package_id.rs
+++ b/src/librustpkg/package_id.rs
@@ -15,6 +15,7 @@ use version::{try_getting_version, try_getting_local_version,
 /// Path-fragment identifier of a package such as
 /// 'github.com/graydon/test'; path must be a relative
 /// path with >=1 component.
+#[deriving(Clone)]
 pub struct PkgId {
     /// Remote path: for example, github.com/mozilla/quux-whatever
     remote_path: RemotePath,
@@ -70,8 +71,8 @@ impl PkgId {
             return cond.raise((p, ~"0-length pkgid"));
         }
         let remote_path = RemotePath(p);
-        let local_path = normalize(copy remote_path);
-        let short_name = (copy local_path).filestem().expect(fmt!("Strange path! %s", s));
+        let local_path = normalize(remote_path.clone());
+        let short_name = local_path.clone().filestem().expect(fmt!("Strange path! %s", s));
 
         let version = match given_version {
             Some(v) => v,
diff --git a/src/librustpkg/package_path.rs b/src/librustpkg/package_path.rs
index a508d2ce153..4ba9c8066e4 100644
--- a/src/librustpkg/package_path.rs
+++ b/src/librustpkg/package_path.rs
@@ -10,17 +10,31 @@
 
 // rustpkg utilities having to do with local and remote paths
 
-use std::path::Path;
-use std::option::Some;
+use std::clone::Clone;
+use std::hash::Streaming;
 use std::hash;
+use std::option::Some;
+use std::path::Path;
 use std::rt::io::Writer;
-use std::hash::Streaming;
 
 /// Wrappers to prevent local and remote paths from getting confused
 /// (These will go away after #6407)
 pub struct RemotePath (Path);
+
+impl Clone for RemotePath {
+    fn clone(&self) -> RemotePath {
+        RemotePath((**self).clone())
+    }
+}
+
 pub struct LocalPath (Path);
 
+impl Clone for LocalPath {
+    fn clone(&self) -> LocalPath {
+        LocalPath((**self).clone())
+    }
+}
+
 
 // normalize should be the only way to construct a LocalPath
 // (though this isn't enforced)
diff --git a/src/librustpkg/package_source.rs b/src/librustpkg/package_source.rs
index 668157bebb9..f7eed969a69 100644
--- a/src/librustpkg/package_source.rs
+++ b/src/librustpkg/package_source.rs
@@ -41,9 +41,9 @@ impl PkgSrc {
     pub fn new(src_dir: &Path, dst_dir: &Path,
                   id: &PkgId) -> PkgSrc {
         PkgSrc {
-            root: copy *src_dir,
-            dst_dir: copy *dst_dir,
-            id: copy *id,
+            root: (*src_dir).clone(),
+            dst_dir: (*dst_dir).clone(),
+            id: (*id).clone(),
             libs: ~[],
             mains: ~[],
             tests: ~[],
@@ -62,15 +62,15 @@ impl PkgSrc {
         debug!("Checking dirs: %?", dirs);
         let path = dirs.iter().find_(|&d| os::path_exists(d));
         match path {
-            Some(d) => dir = copy *d,
+            Some(d) => dir = (*d).clone(),
             None => dir = match self.fetch_git() {
-                None => cond.raise((copy self.id, ~"supplied path for package dir does not \
+                None => cond.raise((self.id.clone(), ~"supplied path for package dir does not \
                                       exist, and couldn't interpret it as a URL fragment")),
                 Some(d) => d
             }
         }
         if !os::path_is_dir(&dir) {
-            cond.raise((copy self.id, ~"supplied path for package dir is a \
+            cond.raise((self.id.clone(), ~"supplied path for package dir is a \
                                         non-directory"));
         }
 
@@ -104,7 +104,7 @@ impl PkgSrc {
         let url = fmt!("https://%s", self.id.remote_path.to_str());
         let branch_args = match self.id.version {
                       NoVersion => ~[],
-                      ExactRevision(ref s) => ~[~"--branch", copy *s],
+                      ExactRevision(ref s) => ~[~"--branch", (*s).clone()],
                       SemanticVersion(ref s) => ~[~"--branch", s.to_str()]
         };
 
@@ -112,7 +112,7 @@ impl PkgSrc {
         note(fmt!("Fetching package: git clone %s %s %?", url, local.to_str(), branch_args));
 
         if run::process_output("git",
-                               ~[~"clone", copy url, local.to_str()] + branch_args).status != 0 {
+                               ~[~"clone", url.clone(), local.to_str()] + branch_args).status != 0 {
             note(fmt!("fetching %s failed: can't clone repository", url));
             None
         }
@@ -199,7 +199,7 @@ impl PkgSrc {
             note("Couldn't infer any crates to build.\n\
                          Try naming a crate `main.rs`, `lib.rs`, \
                          `test.rs`, or `bench.rs`.");
-            cond.raise(copy self.id);
+            cond.raise(self.id.clone());
         }
 
         debug!("found %u libs, %u mains, %u tests, %u benchs",
diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs
index e4a345733ea..a2cae3ab20e 100644
--- a/src/librustpkg/path_util.rs
+++ b/src/librustpkg/path_util.rs
@@ -55,7 +55,7 @@ pub fn rust_path() -> ~[Path] {
     let cwd = os::getcwd();
     // now add in default entries
     env_rust_path.push(cwd.push(".rust"));
-    env_rust_path.push(copy cwd);
+    env_rust_path.push(cwd.clone());
     do cwd.each_parent() |p| { push_if_exists(&mut env_rust_path, p) };
     let h = os::homedir();
     for h.iter().advance |h| { push_if_exists(&mut env_rust_path, h); }
@@ -94,7 +94,7 @@ pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
     let src_dir = workspace.push("src");
     let dirs = os::list_dir(&src_dir);
     for dirs.iter().advance |p| {
-        let p = Path(copy *p);
+        let p = Path((*p).clone());
         debug!("=> p = %s", p.to_str());
         if !os::path_is_dir(&src_dir.push_rel(&p)) {
             loop;
@@ -107,7 +107,7 @@ pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
         else {
             let pf = p.filename();
             for pf.iter().advance |pf| {
-                let f_ = copy *pf;
+                let f_ = (*pf).clone();
                 let g = f_.to_str();
                 match split_version_general(g, '-') {
                     Some((ref might_match, ref vers)) => {
@@ -145,7 +145,7 @@ pub fn first_pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<P
     let rs = pkgid_src_in_workspace(pkgid, workspace);
     for rs.iter().advance |p| {
         if os::path_exists(p) {
-            return Some(copy *p);
+            return Some((*p).clone());
         }
     }
     None
@@ -242,7 +242,7 @@ pub fn library_in_workspace(path: &LocalPath, short_name: &str, where: Target,
     for dir_contents.iter().advance |p| {
         let mut which = 0;
         let mut hash = None;
-        let p_path = Path(copy *p);
+        let p_path = Path((*p).clone());
         let extension = p_path.filetype();
         debug!("p = %s, p's extension is %?", p.to_str(), extension);
         match extension {
@@ -308,7 +308,7 @@ pub fn target_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
 pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
     use conditions::bad_path::cond;
     if !os::path_is_dir(workspace) {
-        cond.raise((copy *workspace,
+        cond.raise(((*workspace).clone(),
                     fmt!("Workspace supplied to target_library_in_workspace \
                           is not a directory! %s", workspace.to_str())));
     }
@@ -341,7 +341,7 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
     };
     let result = workspace.push(subdir);
     if !os::path_exists(&result) && !mkdir_recursive(&result, U_RWX) {
-        cond.raise((copy result, fmt!("target_file_in_workspace couldn't \
+        cond.raise((result.clone(), fmt!("target_file_in_workspace couldn't \
             create the %s dir (pkgid=%s, workspace=%s, what=%?, where=%?",
             subdir, pkgid.to_str(), workspace.to_str(), what, where)));
     }
@@ -375,12 +375,15 @@ pub fn mk_output_path(what: OutputType, where: Target,
     // the executable blat-0.5 to live under blat/
     let dir = match where {
         // If we're installing, it just goes under <workspace>...
-        Install => copy *workspace, // bad copy, but I just couldn't make the borrow checker happy
+        Install => {
+            // bad copy, but I just couldn't make the borrow checker happy
+            (*workspace).clone()
+        }
         // and if we're just building, it goes in a package-specific subdir
         Build => workspace.push_rel(&*pkg_id.local_path)
     };
     debug!("[%?:%?] mk_output_path: short_name = %s, path = %s", what, where,
-           if what == Lib { copy short_name_with_version } else { copy pkg_id.short_name },
+           if what == Lib { short_name_with_version.clone() } else { pkg_id.short_name.clone() },
            dir.to_str());
     let mut output_path = match what {
         // this code is duplicated from elsewhere; fix this
diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs
index 46f2d5eb37e..f2845c00ea6 100644
--- a/src/librustpkg/rustpkg.rs
+++ b/src/librustpkg/rustpkg.rs
@@ -104,12 +104,12 @@ impl<'self> PkgScript<'self> {
             binary: binary,
             maybe_sysroot: Some(@os::self_exe_path().get().pop()),
             crate_type: session::bin_crate,
-            .. copy *session::basic_options()
+            .. (*session::basic_options()).clone()
         };
         let input = driver::file_input(script);
         let sess = driver::build_session(options, diagnostic::emit);
         let cfg = driver::build_configuration(sess, binary, &input);
-        let (crate, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_parse, None);
+        let (crate, _) = driver::compile_upto(sess, cfg.clone(), &input, driver::cu_parse, None);
         let work_dir = build_pkg_id_in_workspace(id, workspace);
 
         debug!("Returning package script with id %?", id);
@@ -203,7 +203,7 @@ impl CtxMethods for Ctx {
                 }
                 // The package id is presumed to be the first command-line
                 // argument
-                let pkgid = PkgId::new(copy args[0], &os::getcwd());
+                let pkgid = PkgId::new(args[0].clone(), &os::getcwd());
                 for each_pkg_parent_workspace(&pkgid) |workspace| {
                     debug!("found pkg %s in workspace %s, trying to build",
                            pkgid.to_str(), workspace.to_str());
@@ -216,7 +216,7 @@ impl CtxMethods for Ctx {
                 }
                 // The package id is presumed to be the first command-line
                 // argument
-                let pkgid = PkgId::new(copy args[0], &os::getcwd());
+                let pkgid = PkgId::new(args[0].clone(), &os::getcwd());
                 let cwd = os::getcwd();
                 self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd
             }
@@ -225,7 +225,7 @@ impl CtxMethods for Ctx {
                     return usage::do_cmd();
                 }
 
-                self.do_cmd(copy args[0], copy args[1]);
+                self.do_cmd(args[0].clone(), args[1].clone());
             }
             "info" => {
                 self.info();
@@ -423,16 +423,16 @@ impl CtxMethods for Ctx {
             debug!("Copying: %s -> %s", exec.to_str(), target_exec.to_str());
             if !(os::mkdir_recursive(&target_exec.dir_path(), U_RWX) &&
                  os::copy_file(exec, &target_exec)) {
-                cond.raise((copy *exec, copy target_exec));
+                cond.raise(((*exec).clone(), target_exec.clone()));
             }
         }
         for maybe_library.iter().advance |lib| {
-            let target_lib = (copy target_lib).expect(fmt!("I built %s but apparently \
+            let target_lib = target_lib.clone().expect(fmt!("I built %s but apparently \
                                                 didn't install it!", lib.to_str()));
             debug!("Copying: %s -> %s", lib.to_str(), target_lib.to_str());
             if !(os::mkdir_recursive(&target_lib.dir_path(), U_RWX) &&
                  os::copy_file(lib, &target_lib)) {
-                cond.raise((copy *lib, copy target_lib));
+                cond.raise(((*lib).clone(), target_lib.clone()));
             }
         }
     }
@@ -475,7 +475,7 @@ pub fn main() {
                getopts::opt_present(matches, "help");
     let json = getopts::opt_present(matches, "j") ||
                getopts::opt_present(matches, "json");
-    let mut args = copy matches.free;
+    let mut args = matches.free.clone();
 
     args.shift();
 
diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs
index 722f01a2564..9d4c2f87a61 100644
--- a/src/librustpkg/tests.rs
+++ b/src/librustpkg/tests.rs
@@ -44,7 +44,7 @@ fn fake_pkg() -> PkgId {
     let sn = ~"bogus";
     let remote = RemotePath(Path(sn));
     PkgId {
-        local_path: normalize(copy remote),
+        local_path: normalize(remote.clone()),
         remote_path: remote,
         short_name: sn,
         version: NoVersion
@@ -54,7 +54,7 @@ fn fake_pkg() -> PkgId {
 fn git_repo_pkg() -> PkgId {
     let remote = RemotePath(Path("mockgithub.com/catamorphism/test-pkg"));
     PkgId {
-        local_path: normalize(copy remote),
+        local_path: normalize(remote.clone()),
         remote_path: remote,
         short_name: ~"test_pkg",
         version: NoVersion
@@ -218,7 +218,7 @@ fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
 fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~str)]>)
     -> ProcessOutput {
     let cmd = test_sysroot().push("bin").push("rustpkg").to_str();
-    let cwd = normalize(RemotePath(copy *cwd));
+    let cwd = normalize(RemotePath((*cwd).clone()));
     debug!("About to run command: %? %? in %s", cmd, args, cwd.to_str());
     assert!(os::path_is_dir(&*cwd));
     let cwd = cwd.clone();
@@ -365,7 +365,7 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
         if p.filetype() == Some(~".rs") {
             // should be able to do this w/o a process
             if run::process_output("touch", [p.to_str()]).status != 0 {
-                let _ = cond.raise((copy pkg_src_dir, ~"Bad path"));
+                let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
             }
             break;
         }
@@ -388,7 +388,7 @@ fn frob_source_file(workspace: &Path, pkgid: &PkgId) {
         Some(p) => {
             let w = io::file_writer(*p, &[io::Append]);
             match w {
-                Err(s) => { let _ = cond.raise((copy **p, fmt!("Bad path: %s", s))); }
+                Err(s) => { let _ = cond.raise(((**p).clone(), fmt!("Bad path: %s", s))); }
                 Ok(w)  => w.write_line("")
             }
         }
@@ -458,7 +458,7 @@ fn test_install_invalid() {
     }).in {
         do cond.trap(|_| {
             error_occurred = true;
-            copy temp_workspace
+            temp_workspace.clone()
         }).in {
             ctxt.install(&temp_workspace, &pkgid);
         }
@@ -542,7 +542,7 @@ fn test_package_ids_must_be_relative_path_like() {
     do cond.trap(|(p, e)| {
         assert!("" == p.to_str());
         assert!("0-length pkgid" == e);
-        copy whatever
+        whatever.clone()
     }).in {
         let x = PkgId::new("", &os::getcwd());
         assert_eq!(~"foo-0.1", x.to_str());
@@ -551,7 +551,7 @@ fn test_package_ids_must_be_relative_path_like() {
     do cond.trap(|(p, e)| {
         assert_eq!(p.to_str(), os::make_absolute(&Path("foo/bar/quux")).to_str());
         assert!("absolute pkgid" == e);
-        copy whatever
+        whatever.clone()
     }).in {
         let z = PkgId::new(os::make_absolute(&Path("foo/bar/quux")).to_str(),
                            &os::getcwd());
diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs
index 009f37c8a49..ef3546efac1 100644
--- a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs
+++ b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs
@@ -27,7 +27,7 @@ pub fn main() {
                argument");
     }
 
-    let sysroot_arg = copy args[1];
+    let sysroot_arg = args[1].clone();
     let sysroot = Path(sysroot_arg);
     if !os::path_exists(&sysroot) {
         fail!("Package script requires a sysroot that exists; %s doesn't", sysroot.to_str());
@@ -53,4 +53,4 @@ pub fn main() {
 
     api::install_lib(@sysroot, os::getcwd(), ~"fancy-lib", Path("lib.rs"),
                      NoVersion);
-}
\ No newline at end of file
+}
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 4a2c2549b0e..d2f5e00513c 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -81,9 +81,13 @@ fn fold_mod(_ctx: @mut ReadyCtx,
     fn strip_main(item: @ast::item) -> @ast::item {
         @ast::item {
             attrs: do item.attrs.iter().filter_map |attr| {
-                if "main" != attr::get_attr_name(attr) {Some(*attr)} else {None}
+                if "main" != attr::get_attr_name(attr) {
+                    Some(*attr)
+                } else {
+                    None
+                }
             }.collect(),
-            .. copy *item
+            .. (*item).clone()
         }
     }
 
@@ -91,7 +95,7 @@ fn fold_mod(_ctx: @mut ReadyCtx,
         items: do m.items.map |item| {
             strip_main(*item)
         },
-        .. copy *m
+        .. (*m).clone()
     }, fold)
 }
 
@@ -122,7 +126,7 @@ fn fold_item(ctx: @mut ReadyCtx,
         ctx.fns.push(ListenerFn {
             cmds: cmds,
             span: item.span,
-            path: /*bad*/copy ctx.path
+            path: /*bad*/ctx.path.clone()
         });
     }
 
@@ -139,7 +143,7 @@ pub fn ready_crate(sess: session::Session,
     let ctx = @mut ReadyCtx {
         sess: sess,
         crate: crate,
-        ext_cx: ExtCtxt::new(sess.parse_sess, copy sess.opts.cfg),
+        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
         path: ~[],
         fns: ~[]
     };
@@ -168,7 +172,7 @@ pub fn compile_input(ctxt: &Ctx,
     let workspace = out_dir.pop().pop();
 
     assert!(in_file.components.len() > 1);
-    let input = driver::file_input(copy *in_file);
+    let input = driver::file_input((*in_file).clone());
     debug!("compile_input: %s / %?", in_file.to_str(), what);
     // tjc: by default, use the package ID name as the link name
     // not sure if we should support anything else
@@ -191,17 +195,17 @@ pub fn compile_input(ctxt: &Ctx,
                               Main => ~[]
                           }
                           + flags
-                          + cfgs.flat_map(|c| { ~[~"--cfg", copy *c] }),
+                          + cfgs.flat_map(|c| { ~[~"--cfg", (*c).clone()] }),
                           driver::optgroups()).get();
     let options = @session::options {
         crate_type: crate_type,
         optimize: if opt { session::Aggressive } else { session::No },
         test: what == Test || what == Bench,
         maybe_sysroot: ctxt.sysroot_opt,
-        addl_lib_search_paths: @mut (~[copy *out_dir]),
+        addl_lib_search_paths: @mut (~[(*out_dir).clone()]),
         // output_type should be conditional
         output_type: output_type_exe, // Use this to get a library? That's weird
-        .. copy *driver::build_session_options(binary, &matches, diagnostic::emit)
+        .. (*driver::build_session_options(binary, &matches, diagnostic::emit)).clone()
     };
 
     let addl_lib_search_paths = @mut options.addl_lib_search_paths;
@@ -216,7 +220,7 @@ pub fn compile_input(ctxt: &Ctx,
     // Infer dependencies that rustpkg needs to build, by scanning for
     // `extern mod` directives.
     let cfg = driver::build_configuration(sess, binary, &input);
-    let (crate_opt, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_expand, None);
+    let (crate_opt, _) = driver::compile_upto(sess, cfg.clone(), &input, driver::cu_expand, None);
 
     let mut crate = match crate_opt {
         Some(c) => c,
@@ -238,7 +242,7 @@ pub fn compile_input(ctxt: &Ctx,
         let short_name_to_use = match what {
             Test  => fmt!("%stest", pkg_id.short_name),
             Bench => fmt!("%sbench", pkg_id.short_name),
-            _     => copy pkg_id.short_name
+            _     => pkg_id.short_name.clone()
         };
         debug!("Injecting link name: %s", short_name_to_use);
         crate = @codemap::respan(crate.span, ast::crate_ {
@@ -248,12 +252,12 @@ pub fn compile_input(ctxt: &Ctx,
                                       mk_string_lit(short_name_to_use.to_managed()))),
                    @dummy_spanned(meta_name_value(@"vers",
                          mk_string_lit(pkg_id.version.to_str().to_managed())))])))],
-            ..copy crate.node});
+            ..crate.node.clone()});
     }
 
     debug!("calling compile_crate_from_input, out_dir = %s,
            building_library = %?", out_dir.to_str(), sess.building_library);
-    compile_crate_from_input(&input, out_dir, sess, crate, copy cfg, driver::cu_expand);
+    compile_crate_from_input(&input, out_dir, sess, crate, cfg.clone(), driver::cu_expand);
     true
 }
 
@@ -272,7 +276,7 @@ pub fn compile_crate_from_input(input: &driver::input,
            build_dir.to_str(), sess.building_library);
 
     // bad copy
-    let outputs = driver::build_output_filenames(input, &Some(copy *build_dir), &None,
+    let outputs = driver::build_output_filenames(input, &Some((*build_dir).clone()), &None,
                                                  crate.node.attrs, sess);
 
     debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type);
@@ -326,7 +330,7 @@ pub fn find_and_install_dependencies(ctxt: &Ctx,
                                 ) {
     // :-(
     debug!("In find_and_install_dependencies...");
-    let my_workspace = copy *workspace;
+    let my_workspace = (*workspace).clone();
     let my_ctxt      = *ctxt;
     for c.each_view_item() |vi: &ast::view_item| {
         debug!("A view item!");
diff --git a/src/librustpkg/version.rs b/src/librustpkg/version.rs
index 5b291164287..9e68ba54b6d 100644
--- a/src/librustpkg/version.rs
+++ b/src/librustpkg/version.rs
@@ -18,6 +18,7 @@ use std::{char, os, result, run, str};
 use package_path::RemotePath;
 use extra::tempfile::mkdtemp;
 
+#[deriving(Clone)]
 pub enum Version {
     ExactRevision(~str), // Should look like a m.n.(...).x
     SemanticVersion(semver::Version),
diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs
index dfd39af093d..13354e61284 100644
--- a/src/libstd/at_vec.rs
+++ b/src/libstd/at_vec.rs
@@ -11,9 +11,9 @@
 //! Managed vectors
 
 use cast::transmute;
+use clone::Clone;
 use container::Container;
 use iterator::IteratorUtil;
-use kinds::Copy;
 use option::Option;
 use sys;
 use uint;
@@ -90,10 +90,14 @@ pub fn build_sized_opt<A>(size: Option<uint>,
 /// Iterates over the `rhs` vector, copying each element and appending it to the
 /// `lhs`. Afterwards, the `lhs` is then returned for use again.
 #[inline]
-pub fn append<T:Copy>(lhs: @[T], rhs: &[T]) -> @[T] {
+pub fn append<T:Clone>(lhs: @[T], rhs: &[T]) -> @[T] {
     do build_sized(lhs.len() + rhs.len()) |push| {
-        for lhs.iter().advance |x| { push(copy *x); }
-        for uint::range(0, rhs.len()) |i| { push(copy rhs[i]); }
+        for lhs.iter().advance |x| {
+            push((*x).clone());
+        }
+        for uint::range(0, rhs.len()) |i| {
+            push(rhs[i].clone());
+        }
     }
 }
 
@@ -126,10 +130,13 @@ pub fn from_fn<T>(n_elts: uint, op: &fn(uint) -> T) -> @[T] {
  * Creates an immutable vector of size `n_elts` and initializes the elements
  * to the value `t`.
  */
-pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> @[T] {
+pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> @[T] {
     do build_sized(n_elts) |push| {
         let mut i: uint = 0u;
-        while i < n_elts { push(copy t); i += 1u; }
+        while i < n_elts {
+            push(t.clone());
+            i += 1u;
+        }
     }
 }
 
@@ -152,18 +159,24 @@ pub fn to_managed_consume<T>(v: ~[T]) -> @[T] {
  * Creates and initializes an immutable managed vector by copying all the
  * elements of a slice.
  */
-pub fn to_managed<T:Copy>(v: &[T]) -> @[T] {
-    from_fn(v.len(), |i| copy v[i])
+pub fn to_managed<T:Clone>(v: &[T]) -> @[T] {
+    from_fn(v.len(), |i| v[i].clone())
+}
+
+impl<T> Clone for @[T] {
+    fn clone(&self) -> @[T] {
+        *self
+    }
 }
 
 #[cfg(not(test))]
 pub mod traits {
     use at_vec::append;
-    use vec::Vector;
-    use kinds::Copy;
+    use clone::Clone;
     use ops::Add;
+    use vec::Vector;
 
-    impl<'self,T:Copy, V: Vector<T>> Add<V,@[T]> for @[T] {
+    impl<'self,T:Clone, V: Vector<T>> Add<V,@[T]> for @[T] {
         #[inline]
         fn add(&self, rhs: &V) -> @[T] {
             append(*self, rhs.as_slice())
diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs
index 50b5b2fcd29..86eec80ae6f 100644
--- a/src/libstd/cast.rs
+++ b/src/libstd/cast.rs
@@ -36,6 +36,14 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
 }
 
 /**
+ * Forces a copy of a value, even if that value is considered noncopyable.
+ */
+#[inline]
+pub unsafe fn unsafe_copy<T>(thing: &T) -> T {
+    transmute_copy(thing)
+}
+
+/**
  * Move a thing into the void
  *
  * The forget function will take ownership of the provided value but neglect
diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs
index 3a5be12b3c5..80caa34ce06 100644
--- a/src/libstd/condition.rs
+++ b/src/libstd/condition.rs
@@ -86,7 +86,7 @@ impl<'self, T, U> Condition<'self, T, U> {
 
     pub fn raise(&self, t: T) -> U {
         let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
-        self.raise_default(t, || fail!(copy msg))
+        self.raise_default(t, || fail!(msg.clone()))
     }
 
     pub fn raise_default(&self, t: T, default: &fn() -> U) -> U {
diff --git a/src/libstd/either.rs b/src/libstd/either.rs
index 8b9b3102831..fcbd98a79e7 100644
--- a/src/libstd/either.rs
+++ b/src/libstd/either.rs
@@ -12,9 +12,9 @@
 
 #[allow(missing_doc)];
 
+use clone::Clone;
 use container::Container;
 use cmp::Eq;
-use kinds::Copy;
 use iterator::IteratorUtil;
 use result::Result;
 use result;
@@ -43,11 +43,11 @@ pub fn either<T, U, V>(f_left: &fn(&T) -> V,
 }
 
 /// Extracts from a vector of either all the left values
-pub fn lefts<T:Copy,U>(eithers: &[Either<T, U>]) -> ~[T] {
+pub fn lefts<T:Clone,U>(eithers: &[Either<T, U>]) -> ~[T] {
     do vec::build_sized(eithers.len()) |push| {
         for eithers.iter().advance |elt| {
             match *elt {
-                Left(ref l) => { push(copy *l); }
+                Left(ref l) => { push((*l).clone()); }
                 _ => { /* fallthrough */ }
             }
         }
@@ -55,11 +55,11 @@ pub fn lefts<T:Copy,U>(eithers: &[Either<T, U>]) -> ~[T] {
 }
 
 /// Extracts from a vector of either all the right values
-pub fn rights<T, U: Copy>(eithers: &[Either<T, U>]) -> ~[U] {
+pub fn rights<T, U: Clone>(eithers: &[Either<T, U>]) -> ~[U] {
     do vec::build_sized(eithers.len()) |push| {
         for eithers.iter().advance |elt| {
             match *elt {
-                Right(ref r) => { push(copy *r); }
+                Right(ref r) => { push((*r).clone()); }
                 _ => { /* fallthrough */ }
             }
         }
diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs
index 79c6c4fb21d..7cf2c594202 100644
--- a/src/libstd/hashmap.rs
+++ b/src/libstd/hashmap.rs
@@ -25,10 +25,9 @@ use option::{None, Option, Some};
 use rand::RngUtil;
 use rand;
 use uint;
-use vec;
-use vec::{ImmutableVector, MutableVector, OwnedVector};
-use kinds::Copy;
 use util::{replace, unreachable};
+use vec::{ImmutableVector, MutableVector, OwnedVector};
+use vec;
 
 static INITIAL_CAPACITY: uint = 32u; // 2^5
 
@@ -525,15 +524,15 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
     }
 }
 
-impl<K: Hash + Eq, V: Copy> HashMap<K, V> {
+impl<K: Hash + Eq, V: Clone> HashMap<K, V> {
     /// Like `find`, but returns a copy of the value.
     pub fn find_copy(&self, k: &K) -> Option<V> {
-        self.find(k).map_consume(|v| copy *v)
+        self.find(k).map_consume(|v| (*v).clone())
     }
 
     /// Like `get`, but returns a copy of the value.
     pub fn get_copy(&self, k: &K) -> V {
-        copy *self.get(k)
+        (*self.get(k)).clone()
     }
 }
 
@@ -554,6 +553,16 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
     fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) }
 }
 
+impl<K:Hash + Eq + Clone,V:Clone> Clone for HashMap<K,V> {
+    fn clone(&self) -> HashMap<K,V> {
+        let mut new_map = HashMap::with_capacity(self.len());
+        for self.iter().advance |(key, value)| {
+            new_map.insert((*key).clone(), (*value).clone());
+        }
+        new_map
+    }
+}
+
 /// HashMap iterator
 pub struct HashMapIterator<'self, K, V> {
     priv iter: vec::VecIterator<'self, Option<Bucket<K, V>>>,
diff --git a/src/libstd/io.rs b/src/libstd/io.rs
index 347fa988856..e074eba68ae 100644
--- a/src/libstd/io.rs
+++ b/src/libstd/io.rs
@@ -48,6 +48,7 @@ implement `Reader` and `Writer`, where appropriate.
 
 use result::Result;
 
+use clone::Clone;
 use container::Container;
 use int;
 use libc;
@@ -1697,7 +1698,7 @@ pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
     let wr = @BytesWriter::new();
     f(wr as @Writer);
     let @BytesWriter { bytes, _ } = wr;
-    copy *bytes
+    (*bytes).clone()
 }
 
 pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
@@ -1750,7 +1751,6 @@ pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
 
 pub mod fsync {
     use io::{FILERes, FdRes, fd_t};
-    use kinds::Copy;
     use libc;
     use ops::Drop;
     use option::{None, Option, Some};
@@ -1775,21 +1775,20 @@ pub mod fsync {
         arg: Arg<t>,
     }
 
-    impl <t: Copy> Res<t> {
+    impl <t> Res<t> {
         pub fn new(arg: Arg<t>) -> Res<t> {
             Res { arg: arg }
         }
     }
 
     #[unsafe_destructor]
-    impl<T:Copy> Drop for Res<T> {
+    impl<T> Drop for Res<T> {
         fn drop(&self) {
             match self.arg.opt_level {
                 None => (),
                 Some(level) => {
                   // fail hard if not succesful
-                  assert!(((self.arg.fsync_fn)(copy self.arg.val, level)
-                    != -1));
+                  assert!(((self.arg.fsync_fn)(&self.arg.val, level) != -1));
                 }
             }
         }
@@ -1798,7 +1797,7 @@ pub mod fsync {
     pub struct Arg<t> {
         val: t,
         opt_level: Option<Level>,
-        fsync_fn: @fn(f: t, Level) -> int,
+        fsync_fn: @fn(f: &t, Level) -> int,
     }
 
     // fsync file after executing blk
@@ -1810,7 +1809,7 @@ pub mod fsync {
             val: file.f, opt_level: opt_level,
             fsync_fn: |file, l| {
                 unsafe {
-                    os::fsync_fd(libc::fileno(file), l) as int
+                    os::fsync_fd(libc::fileno(*file), l) as int
                 }
             }
         }));
@@ -1821,7 +1820,7 @@ pub mod fsync {
                        blk: &fn(v: Res<fd_t>)) {
         blk(Res::new(Arg {
             val: fd.fd, opt_level: opt_level,
-            fsync_fn: |fd, l| os::fsync_fd(fd, l) as int
+            fsync_fn: |fd, l| os::fsync_fd(*fd, l) as int
         }));
     }
 
@@ -1833,7 +1832,7 @@ pub mod fsync {
                     blk: &fn(v: Res<@FSyncable>)) {
         blk(Res::new(Arg {
             val: o, opt_level: opt_level,
-            fsync_fn: |o, l| o.fsync(l)
+            fsync_fn: |o, l| (*o).fsync(l)
         }));
     }
 }
@@ -1854,7 +1853,7 @@ mod tests {
         debug!(tmpfile);
         let frood: ~str =
             ~"A hoopy frood who really knows where his towel is.";
-        debug!(copy frood);
+        debug!(frood.clone());
         {
             let out: @io::Writer =
                 result::get(
@@ -1863,7 +1862,7 @@ mod tests {
         }
         let inp: @io::Reader = result::get(&io::file_reader(tmpfile));
         let frood2: ~str = inp.read_c_str();
-        debug!(copy frood2);
+        debug!(frood2.clone());
         assert_eq!(frood, frood2);
     }
 
diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs
index 6c1640e683e..168bb7c14f0 100644
--- a/src/libstd/local_data.rs
+++ b/src/libstd/local_data.rs
@@ -135,9 +135,11 @@ pub fn modify<T: 'static>(key: Key<@T>, f: &fn(Option<@T>) -> Option<@T>) {
  */
 #[cfg(not(stage0))]
 pub fn modify<T: 'static>(key: Key<T>, f: &fn(Option<T>) -> Option<T>) {
-    match f(pop(key)) {
-        Some(next) => { set(key, next); }
-        None => {}
+    unsafe {
+        match f(pop(::cast::unsafe_copy(&key))) {
+            Some(next) => { set(key, next); }
+            None => {}
+        }
     }
 }
 
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index 337d804ce73..4661bc20403 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -10,6 +10,7 @@
 
 #[allow(missing_doc)];
 
+use clone::Clone;
 use container::Container;
 use core::cmp::{Ord, Eq};
 use ops::{Add, Sub, Mul, Div, Rem, Neg};
@@ -467,7 +468,7 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
  */
 pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
                                     Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
-                                    NumStrConv>(
+                                    NumStrConv+Clone>(
         buf: &[u8], radix: uint, negative: bool, fractional: bool,
         special: bool, exponent: ExponentFormat, empty_zero: bool,
         ignore_underscores: bool
@@ -528,8 +529,8 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
 
     // Initialize accumulator with signed zero for floating point parsing to
     // work
-    let mut accum      = if accum_positive { copy _0 } else { -_1 * _0};
-    let mut last_accum = copy accum; // Necessary to detect overflow
+    let mut accum      = if accum_positive { _0.clone() } else { -_1 * _0};
+    let mut last_accum = accum.clone(); // Necessary to detect overflow
     let mut i          = start;
     let mut exp_found  = false;
 
@@ -540,7 +541,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
         match char::to_digit(c, radix) {
             Some(digit) => {
                 // shift accum one digit left
-                accum = accum * copy radix_gen;
+                accum = accum * radix_gen.clone();
 
                 // add/subtract current digit depending on sign
                 if accum_positive {
@@ -555,7 +556,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
                     if accum_positive && accum <= last_accum { return None; }
                     if !accum_positive && accum >= last_accum { return None; }
                 }
-                last_accum = copy accum;
+                last_accum = accum.clone();
             }
             None => match c {
                 '_' if ignore_underscores => {}
@@ -577,7 +578,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
     // Parse fractional part of number
     // Skip if already reached start of exponent
     if !exp_found {
-        let mut power = copy _1;
+        let mut power = _1.clone();
 
         while i < len {
             let c = buf[i] as char;
@@ -599,7 +600,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
                     // Detect overflow by comparing to last value
                     if accum_positive && accum < last_accum { return None; }
                     if !accum_positive && accum > last_accum { return None; }
-                    last_accum = copy accum;
+                    last_accum = accum.clone();
                 }
                 None => match c {
                     '_' if ignore_underscores => {}
@@ -625,7 +626,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
         }
     }
 
-    let mut multiplier = copy _1;
+    let mut multiplier = _1.clone();
 
     if exp_found {
         let c = buf[i] as char;
@@ -663,7 +664,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
  */
 #[inline]
 pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+Mul<T,T>+
-                              Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv>(
+                              Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv+Clone>(
         buf: &str, radix: uint, negative: bool, fractional: bool,
         special: bool, exponent: ExponentFormat, empty_zero: bool,
         ignore_underscores: bool
diff --git a/src/libstd/option.rs b/src/libstd/option.rs
index b0811674a7b..42d892fee9b 100644
--- a/src/libstd/option.rs
+++ b/src/libstd/option.rs
@@ -41,9 +41,9 @@ let unwrapped_msg = match msg {
 
 */
 
+use clone::Clone;
 use cmp::{Eq,Ord};
 use ops::Add;
-use kinds::Copy;
 use util;
 use num::Zero;
 use iterator::Iterator;
@@ -88,13 +88,13 @@ impl<T:Ord> Ord for Option<T> {
     }
 }
 
-impl<T: Copy+Add<T,T>> Add<Option<T>, Option<T>> for Option<T> {
+impl<T:Clone+Add<T,T>> Add<Option<T>, Option<T>> for Option<T> {
     #[inline]
     fn add(&self, other: &Option<T>) -> Option<T> {
         match (&*self, &*other) {
             (&None, &None) => None,
-            (_, &None) => copy *self,
-            (&None, _) => copy *other,
+            (_, &None) => (*self).clone(),
+            (&None, _) => (*other).clone(),
             (&Some(ref lhs), &Some(ref rhs)) => Some(*lhs + *rhs)
         }
     }
@@ -313,9 +313,7 @@ impl<T> Option<T> {
           None => fail!(reason.to_owned()),
         }
     }
-}
 
-impl<T:Copy> Option<T> {
     /**
     Gets the value out of an option
 
@@ -354,7 +352,7 @@ impl<T:Copy> Option<T> {
     }
 }
 
-impl<T:Copy + Zero> Option<T> {
+impl<T:Zero> Option<T> {
     /// Returns the contained value or zero (for this type)
     #[inline]
     pub fn get_or_zero(self) -> T {
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 58175db1241..c54cf3910bd 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -29,6 +29,7 @@
 #[allow(missing_doc)];
 
 use cast;
+use clone::Clone;
 use container::Container;
 use io;
 use iterator::IteratorUtil;
@@ -630,7 +631,7 @@ pub fn path_exists(p: &Path) -> bool {
 // the input paths.
 pub fn make_absolute(p: &Path) -> Path {
     if p.is_absolute {
-        copy *p
+        (*p).clone()
     } else {
         getcwd().push_many(p.components)
     }
@@ -1252,7 +1253,7 @@ static overridden_arg_key: local_data::Key<@OverriddenArgs> = &local_data::Key;
 pub fn args() -> ~[~str] {
     match local_data::get(overridden_arg_key, |k| k.map(|&k| *k)) {
         None => real_args(),
-        Some(args) => copy args.val
+        Some(args) => args.val.clone()
     }
 }
 
@@ -1260,7 +1261,9 @@ pub fn args() -> ~[~str] {
 /// program had when it started. These new arguments are only available to the
 /// current task via the `os::args` method.
 pub fn set_args(new_args: ~[~str]) {
-    let overridden_args = @OverriddenArgs { val: copy new_args };
+    let overridden_args = @OverriddenArgs {
+        val: new_args.clone()
+    };
     local_data::set(overridden_arg_key, overridden_args);
 }
 
@@ -1807,7 +1810,7 @@ mod tests {
         }
         let n = make_rand_name();
         setenv(n, s);
-        debug!(copy s);
+        debug!(s.clone());
         assert_eq!(getenv(n), option::Some(s));
     }
 
@@ -1816,7 +1819,7 @@ mod tests {
         let path = os::self_exe_path();
         assert!(path.is_some());
         let path = path.get();
-        debug!(copy path);
+        debug!(path.clone());
 
         // Hard to test this function
         assert!(path.is_absolute);
@@ -1828,8 +1831,8 @@ mod tests {
         let e = env();
         assert!(e.len() > 0u);
         for e.iter().advance |p| {
-            let (n, v) = copy *p;
-            debug!(copy n);
+            let (n, v) = (*p).clone();
+            debug!(n.clone());
             let v2 = getenv(n);
             // MingW seems to set some funky environment variables like
             // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned
@@ -1844,7 +1847,7 @@ mod tests {
 
         let mut e = env();
         setenv(n, "VALUE");
-        assert!(!e.contains(&(copy n, ~"VALUE")));
+        assert!(!e.contains(&(n.clone(), ~"VALUE")));
 
         e = env();
         assert!(e.contains(&(n, ~"VALUE")));
@@ -1920,7 +1923,7 @@ mod tests {
         assert!(dirs.len() > 0u);
 
         for dirs.iter().advance |dir| {
-            debug!(copy *dir);
+            debug!((*dir).clone());
         }
     }
 
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index a5e82c31d79..fe298931d42 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -16,6 +16,7 @@ Cross-platform file path handling
 
 #[allow(missing_doc)];
 
+use clone::Clone;
 use container::Container;
 use cmp::Eq;
 use iterator::IteratorUtil;
@@ -553,7 +554,7 @@ impl GenericPath for PosixPath {
     fn filename(&self) -> Option<~str> {
         match self.components.len() {
             0 => None,
-            n => Some(copy self.components[n - 1]),
+            n => Some(self.components[n - 1].clone()),
         }
     }
 
@@ -563,7 +564,7 @@ impl GenericPath for PosixPath {
             Some(ref f) => {
                 match f.rfind('.') {
                     Some(p) => Some(f.slice_to(p).to_owned()),
-                    None => Some(copy *f),
+                    None => Some((*f).clone()),
                 }
             }
         }
@@ -603,7 +604,7 @@ impl GenericPath for PosixPath {
 
     fn with_filetype(&self, t: &str) -> PosixPath {
         match (t.len(), self.filestem()) {
-            (0, None)        => copy *self,
+            (0, None)        => (*self).clone(),
             (0, Some(ref s)) => self.with_filename(*s),
             (_, None)        => self.with_filename(fmt!(".%s", t)),
             (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)),
@@ -612,7 +613,7 @@ impl GenericPath for PosixPath {
 
     fn dir_path(&self) -> PosixPath {
         match self.components.len() {
-            0 => copy *self,
+            0 => (*self).clone(),
             _ => self.pop(),
         }
     }
@@ -620,7 +621,7 @@ impl GenericPath for PosixPath {
     fn file_path(&self) -> PosixPath {
         let cs = match self.filename() {
           None => ~[],
-          Some(ref f) => ~[copy *f]
+          Some(ref f) => ~[(*f).clone()]
         };
         PosixPath {
             is_absolute: false,
@@ -637,7 +638,7 @@ impl GenericPath for PosixPath {
         if other.is_absolute {
             PosixPath {
                 is_absolute: true,
-                components: copy other.components,
+                components: other.components.clone(),
             }
         } else {
             self.push_rel(other)
@@ -649,7 +650,7 @@ impl GenericPath for PosixPath {
     }
 
     fn push_many<S: Str>(&self, cs: &[S]) -> PosixPath {
-        let mut v = copy self.components;
+        let mut v = self.components.clone();
         for cs.iter().advance |e| {
             for e.as_slice().split_iter(windows::is_sep).advance |s| {
                 if !s.is_empty() {
@@ -664,17 +665,20 @@ impl GenericPath for PosixPath {
     }
 
     fn push(&self, s: &str) -> PosixPath {
-        let mut v = copy self.components;
+        let mut v = self.components.clone();
         for s.split_iter(windows::is_sep).advance |s| {
             if !s.is_empty() {
                 v.push(s.to_owned())
             }
         }
-        PosixPath { components: v, ..copy *self }
+        PosixPath {
+            components: v,
+            ..(*self).clone()
+        }
     }
 
     fn pop(&self) -> PosixPath {
-        let mut cs = copy self.components;
+        let mut cs = self.components.clone();
         if cs.len() != 0 {
             cs.pop();
         }
@@ -734,13 +738,13 @@ impl GenericPath for WindowsPath {
         ) {
             (Some((ref d, ref r)), _) => {
                 host = None;
-                device = Some(copy *d);
-                rest = copy *r;
+                device = Some((*d).clone());
+                rest = (*r).clone();
             }
             (None, Some((ref h, ref r))) => {
-                host = Some(copy *h);
+                host = Some((*h).clone());
                 device = None;
-                rest = copy *r;
+                rest = (*r).clone();
             }
             (None, None) => {
                 host = None;
@@ -773,7 +777,7 @@ impl GenericPath for WindowsPath {
     fn filename(&self) -> Option<~str> {
         match self.components.len() {
             0 => None,
-            n => Some(copy self.components[n - 1]),
+            n => Some(self.components[n - 1].clone()),
         }
     }
 
@@ -783,7 +787,7 @@ impl GenericPath for WindowsPath {
             Some(ref f) => {
                 match f.rfind('.') {
                     Some(p) => Some(f.slice_to(p).to_owned()),
-                    None => Some(copy *f),
+                    None => Some((*f).clone()),
                 }
             }
         }
@@ -823,7 +827,7 @@ impl GenericPath for WindowsPath {
 
     fn with_filetype(&self, t: &str) -> WindowsPath {
         match (t.len(), self.filestem()) {
-            (0, None)        => copy *self,
+            (0, None)        => (*self).clone(),
             (0, Some(ref s)) => self.with_filename(*s),
             (_, None)        => self.with_filename(fmt!(".%s", t)),
             (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)),
@@ -832,7 +836,7 @@ impl GenericPath for WindowsPath {
 
     fn dir_path(&self) -> WindowsPath {
         match self.components.len() {
-            0 => copy *self,
+            0 => (*self).clone(),
             _ => self.pop(),
         }
     }
@@ -844,7 +848,7 @@ impl GenericPath for WindowsPath {
             is_absolute: false,
             components: match self.filename() {
                 None => ~[],
-                Some(ref f) => ~[copy *f],
+                Some(ref f) => ~[(*f).clone()],
             }
         }
     }
@@ -864,10 +868,10 @@ impl GenericPath for WindowsPath {
         match other.host {
             Some(ref host) => {
                 return WindowsPath {
-                    host: Some(copy *host),
-                    device: copy other.device,
+                    host: Some((*host).clone()),
+                    device: other.device.clone(),
                     is_absolute: true,
-                    components: copy other.components,
+                    components: other.components.clone(),
                 };
             }
             _ => {}
@@ -878,9 +882,9 @@ impl GenericPath for WindowsPath {
             Some(ref device) => {
                 return WindowsPath {
                     host: None,
-                    device: Some(copy *device),
+                    device: Some((*device).clone()),
                     is_absolute: true,
-                    components: copy other.components,
+                    components: other.components.clone(),
                 };
             }
             _ => {}
@@ -889,10 +893,10 @@ impl GenericPath for WindowsPath {
         /* fallback: host and device of lhs win, but the
            whole path of the right */
         WindowsPath {
-            host: copy self.host,
-            device: copy self.device,
+            host: self.host.clone(),
+            device: self.device.clone(),
             is_absolute: self.is_absolute || other.is_absolute,
-            components: copy other.components,
+            components: other.components.clone(),
         }
     }
 
@@ -912,7 +916,7 @@ impl GenericPath for WindowsPath {
     }
 
     fn push_many<S: Str>(&self, cs: &[S]) -> WindowsPath {
-        let mut v = copy self.components;
+        let mut v = self.components.clone();
         for cs.iter().advance |e| {
             for e.as_slice().split_iter(windows::is_sep).advance |s| {
                 if !s.is_empty() {
@@ -922,31 +926,31 @@ impl GenericPath for WindowsPath {
         }
         // tedious, but as-is, we can't use ..self
         WindowsPath {
-            host: copy self.host,
-            device: copy self.device,
+            host: self.host.clone(),
+            device: self.device.clone(),
             is_absolute: self.is_absolute,
             components: v
         }
     }
 
     fn push(&self, s: &str) -> WindowsPath {
-        let mut v = copy self.components;
+        let mut v = self.components.clone();
         for s.split_iter(windows::is_sep).advance |s| {
             if !s.is_empty() {
                 v.push(s.to_owned())
             }
         }
-        WindowsPath { components: v, ..copy *self }
+        WindowsPath { components: v, ..(*self).clone() }
     }
 
     fn pop(&self) -> WindowsPath {
-        let mut cs = copy self.components;
+        let mut cs = self.components.clone();
         if cs.len() != 0 {
             cs.pop();
         }
         WindowsPath {
-            host: copy self.host,
-            device: copy self.device,
+            host: self.host.clone(),
+            device: self.device.clone(),
             is_absolute: self.is_absolute,
             components: cs,
         }
@@ -954,7 +958,7 @@ impl GenericPath for WindowsPath {
 
     fn normalize(&self) -> WindowsPath {
         WindowsPath {
-            host: copy self.host,
+            host: self.host.clone(),
             device: match self.device {
                 None => None,
 
@@ -982,7 +986,7 @@ pub fn normalize(components: &[~str]) -> ~[~str] {
             cs.pop();
             loop;
         }
-        cs.push(copy *c);
+        cs.push((*c).clone());
     }
     cs
 }
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
index e1a62b26bbf..caf15120bd7 100644
--- a/src/libstd/ptr.rs
+++ b/src/libstd/ptr.rs
@@ -11,6 +11,7 @@
 //! Unsafe pointer utility functions
 
 use cast;
+use clone::Clone;
 use option::{Option, Some, None};
 use sys;
 use unstable::intrinsics;
@@ -45,6 +46,12 @@ pub unsafe fn buf_len<T>(buf: **T) -> uint {
     position(buf, |i| *i == null())
 }
 
+impl<T> Clone for *T {
+    fn clone(&self) -> *T {
+        *self
+    }
+}
+
 /// Return the first offset `i` such that `f(buf[i]) == true`.
 #[inline]
 pub unsafe fn position<T>(buf: *T, f: &fn(&T) -> bool) -> uint {
@@ -617,7 +624,7 @@ pub mod ptr_tests {
             array_each_with_len(arr_ptr, arr.len(),
                                 |e| {
                                          let actual = str::raw::from_c_str(e);
-                                         let expected = copy expected_arr[ctr];
+                                         let expected = expected_arr[ctr].clone();
                                          debug!(
                                              "test_ptr_array_each e: %s, a: %s",
                                              expected, actual);
@@ -649,7 +656,7 @@ pub mod ptr_tests {
             let mut iteration_count = 0;
             array_each(arr_ptr, |e| {
                 let actual = str::raw::from_c_str(e);
-                let expected = copy expected_arr[ctr];
+                let expected = expected_arr[ctr].clone();
                 debug!(
                     "test_ptr_array_each e: %s, a: %s",
                     expected, actual);
diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs
index 6f89e7ffb07..7d65ba63ff0 100644
--- a/src/libstd/rand.rs
+++ b/src/libstd/rand.rs
@@ -44,6 +44,7 @@ fn main () {
 */
 
 use cast;
+use clone::Clone;
 use cmp;
 use container::Container;
 use int;
@@ -355,9 +356,9 @@ pub trait RngUtil {
      * }
      * ~~~
      */
-    fn choose<T:Copy>(&mut self, values: &[T]) -> T;
+    fn choose<T:Copy + Clone>(&mut self, values: &[T]) -> T;
     /// Choose Some(item) randomly, returning None if values is empty
-    fn choose_option<T:Copy>(&mut self, values: &[T]) -> Option<T>;
+    fn choose_option<T:Clone>(&mut self, values: &[T]) -> Option<T>;
     /**
      * Choose an item respecting the relative weights, failing if the sum of
      * the weights is 0
@@ -378,7 +379,7 @@ pub trait RngUtil {
      * }
      * ~~~
      */
-    fn choose_weighted<T:Copy>(&mut self, v : &[Weighted<T>]) -> T;
+    fn choose_weighted<T:Copy + Clone>(&mut self, v : &[Weighted<T>]) -> T;
     /**
      * Choose Some(item) respecting the relative weights, returning none if
      * the sum of the weights is 0
@@ -399,7 +400,7 @@ pub trait RngUtil {
      * }
      * ~~~
      */
-    fn choose_weighted_option<T:Copy>(&mut self, v: &[Weighted<T>])
+    fn choose_weighted_option<T:Clone>(&mut self, v: &[Weighted<T>])
                                      -> Option<T>;
     /**
      * Return a vec containing copies of the items, in order, where
@@ -421,7 +422,7 @@ pub trait RngUtil {
      * }
      * ~~~
      */
-    fn weighted_vec<T:Copy>(&mut self, v: &[Weighted<T>]) -> ~[T];
+    fn weighted_vec<T:Clone>(&mut self, v: &[Weighted<T>]) -> ~[T];
     /**
      * Shuffle a vec
      *
@@ -438,7 +439,7 @@ pub trait RngUtil {
      * }
      * ~~~
      */
-    fn shuffle<T:Copy>(&mut self, values: &[T]) -> ~[T];
+    fn shuffle<T:Copy + Clone>(&mut self, values: &[T]) -> ~[T];
     /**
      * Shuffle a mutable vec in place
      *
@@ -531,23 +532,23 @@ impl<R: Rng> RngUtil for R {
     }
 
     /// Choose an item randomly, failing if values is empty
-    fn choose<T:Copy>(&mut self, values: &[T]) -> T {
+    fn choose<T:Copy + Clone>(&mut self, values: &[T]) -> T {
         self.choose_option(values).get()
     }
 
     /// Choose Some(item) randomly, returning None if values is empty
-    fn choose_option<T:Copy>(&mut self, values: &[T]) -> Option<T> {
+    fn choose_option<T:Clone>(&mut self, values: &[T]) -> Option<T> {
         if values.is_empty() {
             None
         } else {
-            Some(copy values[self.gen_uint_range(0u, values.len())])
+            Some(values[self.gen_uint_range(0u, values.len())].clone())
         }
     }
     /**
      * Choose an item respecting the relative weights, failing if the sum of
      * the weights is 0
      */
-    fn choose_weighted<T:Copy>(&mut self, v: &[Weighted<T>]) -> T {
+    fn choose_weighted<T:Copy + Clone>(&mut self, v: &[Weighted<T>]) -> T {
         self.choose_weighted_option(v).get()
     }
 
@@ -555,8 +556,8 @@ impl<R: Rng> RngUtil for R {
      * Choose Some(item) respecting the relative weights, returning none if
      * the sum of the weights is 0
      */
-    fn choose_weighted_option<T:Copy>(&mut self, v: &[Weighted<T>])
-                                     -> Option<T> {
+    fn choose_weighted_option<T:Clone>(&mut self, v: &[Weighted<T>])
+                                       -> Option<T> {
         let mut total = 0u;
         for v.iter().advance |item| {
             total += item.weight;
@@ -569,7 +570,7 @@ impl<R: Rng> RngUtil for R {
         for v.iter().advance |item| {
             so_far += item.weight;
             if so_far > chosen {
-                return Some(copy item.item);
+                return Some(item.item.clone());
             }
         }
         util::unreachable();
@@ -579,18 +580,18 @@ impl<R: Rng> RngUtil for R {
      * Return a vec containing copies of the items, in order, where
      * the weight of the item determines how many copies there are
      */
-    fn weighted_vec<T:Copy>(&mut self, v: &[Weighted<T>]) -> ~[T] {
+    fn weighted_vec<T:Clone>(&mut self, v: &[Weighted<T>]) -> ~[T] {
         let mut r = ~[];
         for v.iter().advance |item| {
             for uint::range(0u, item.weight) |_i| {
-                r.push(copy item.item);
+                r.push(item.item.clone());
             }
         }
         r
     }
 
     /// Shuffle a vec
-    fn shuffle<T:Copy>(&mut self, values: &[T]) -> ~[T] {
+    fn shuffle<T:Copy + Clone>(&mut self, values: &[T]) -> ~[T] {
         let mut m = values.to_owned();
         self.shuffle_mut(m);
         m
diff --git a/src/libstd/result.rs b/src/libstd/result.rs
index 0b099b66ecf..4fdcf9bb0b3 100644
--- a/src/libstd/result.rs
+++ b/src/libstd/result.rs
@@ -12,10 +12,10 @@
 
 #[allow(missing_doc)];
 
+use clone::Clone;
 use cmp::Eq;
 use either;
 use either::Either;
-use kinds::Copy;
 use iterator::IteratorUtil;
 use option::{None, Option, Some};
 use vec;
@@ -39,9 +39,9 @@ pub enum Result<T, U> {
  * If the result is an error
  */
 #[inline]
-pub fn get<T:Copy,U>(res: &Result<T, U>) -> T {
+pub fn get<T:Clone,U>(res: &Result<T, U>) -> T {
     match *res {
-      Ok(ref t) => copy *t,
+      Ok(ref t) => (*t).clone(),
       Err(ref the_err) =>
         fail!("get called on error result: %?", *the_err)
     }
@@ -71,9 +71,9 @@ pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T {
  * If the result is not an error
  */
 #[inline]
-pub fn get_err<T, U: Copy>(res: &Result<T, U>) -> U {
+pub fn get_err<T, U: Clone>(res: &Result<T, U>) -> U {
     match *res {
-      Err(ref u) => copy *u,
+      Err(ref u) => (*u).clone(),
       Ok(_) => fail!("get_err called on ok result")
     }
 }
@@ -100,11 +100,11 @@ pub fn is_err<T, U>(res: &Result<T, U>) -> bool {
  * result variants are converted to `either::left`.
  */
 #[inline]
-pub fn to_either<T:Copy,U:Copy>(res: &Result<U, T>)
+pub fn to_either<T:Clone,U:Clone>(res: &Result<U, T>)
     -> Either<T, U> {
     match *res {
-      Ok(ref res) => either::Right(copy *res),
-      Err(ref fail_) => either::Left(copy *fail_)
+      Ok(ref res) => either::Right((*res).clone()),
+      Err(ref fail_) => either::Left((*fail_).clone())
     }
 }
 
@@ -203,11 +203,11 @@ pub fn iter_err<T, E>(res: &Result<T, E>, f: &fn(&E)) {
  *     }
  */
 #[inline]
-pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U)
+pub fn map<T, E: Clone, U: Clone>(res: &Result<T, E>, op: &fn(&T) -> U)
   -> Result<U, E> {
     match *res {
       Ok(ref t) => Ok(op(t)),
-      Err(ref e) => Err(copy *e)
+      Err(ref e) => Err((*e).clone())
     }
 }
 
@@ -220,10 +220,10 @@ pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U)
  * successful result while handling an error.
  */
 #[inline]
-pub fn map_err<T:Copy,E,F:Copy>(res: &Result<T, E>, op: &fn(&E) -> F)
+pub fn map_err<T:Clone,E,F:Clone>(res: &Result<T, E>, op: &fn(&E) -> F)
   -> Result<T, F> {
     match *res {
-      Ok(ref t) => Ok(copy *t),
+      Ok(ref t) => Ok((*t).clone()),
       Err(ref e) => Err(op(e))
     }
 }
@@ -261,22 +261,22 @@ impl<T, E> Result<T, E> {
     }
 }
 
-impl<T:Copy,E> Result<T, E> {
+impl<T:Clone,E> Result<T, E> {
     #[inline]
     pub fn get(&self) -> T { get(self) }
 
     #[inline]
-    pub fn map_err<F:Copy>(&self, op: &fn(&E) -> F) -> Result<T,F> {
+    pub fn map_err<F:Clone>(&self, op: &fn(&E) -> F) -> Result<T,F> {
         map_err(self, op)
     }
 }
 
-impl<T, E: Copy> Result<T, E> {
+impl<T, E:Clone> Result<T, E> {
     #[inline]
     pub fn get_err(&self) -> E { get_err(self) }
 
     #[inline]
-    pub fn map<U:Copy>(&self, op: &fn(&T) -> U) -> Result<U,E> {
+    pub fn map<U:Clone>(&self, op: &fn(&T) -> U) -> Result<U,E> {
         map(self, op)
     }
 }
@@ -299,9 +299,8 @@ impl<T, E: Copy> Result<T, E> {
  *     }
  */
 #[inline]
-pub fn map_vec<T,U:Copy,V:Copy>(
-    ts: &[T], op: &fn(&T) -> Result<V,U>) -> Result<~[V],U> {
-
+pub fn map_vec<T,U,V>(ts: &[T], op: &fn(&T) -> Result<V,U>)
+                      -> Result<~[V],U> {
     let mut vs: ~[V] = vec::with_capacity(ts.len());
     for ts.iter().advance |t| {
         match op(t) {
@@ -314,15 +313,18 @@ pub fn map_vec<T,U:Copy,V:Copy>(
 
 #[inline]
 #[allow(missing_doc)]
-pub fn map_opt<T,U:Copy,V:Copy>(
-    o_t: &Option<T>, op: &fn(&T) -> Result<V,U>) -> Result<Option<V>,U> {
-
+pub fn map_opt<T,
+               U,
+               V>(
+               o_t: &Option<T>,
+               op: &fn(&T) -> Result<V,U>)
+               -> Result<Option<V>,U> {
     match *o_t {
-      None => Ok(None),
-      Some(ref t) => match op(t) {
-        Ok(v) => Ok(Some(v)),
-        Err(e) => Err(e)
-      }
+        None => Ok(None),
+        Some(ref t) => match op(t) {
+            Ok(v) => Ok(Some(v)),
+            Err(e) => Err(e)
+        }
     }
 }
 
@@ -336,7 +338,7 @@ pub fn map_opt<T,U:Copy,V:Copy>(
  * to accommodate an error like the vectors being of different lengths.
  */
 #[inline]
-pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T],
+pub fn map_vec2<S,T,U,V>(ss: &[S], ts: &[T],
                 op: &fn(&S,&T) -> Result<V,U>) -> Result<~[V],U> {
 
     assert!(vec::same_length(ss, ts));
@@ -359,7 +361,7 @@ pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T],
  * on its own as no result vector is built.
  */
 #[inline]
-pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T],
+pub fn iter_vec2<S,T,U>(ss: &[S], ts: &[T],
                          op: &fn(&S,&T) -> Result<(),U>) -> Result<(),U> {
 
     assert!(vec::same_length(ss, ts));
diff --git a/src/libstd/rt/join_latch.rs b/src/libstd/rt/join_latch.rs
index 8073c4a75b8..924db1a21b7 100644
--- a/src/libstd/rt/join_latch.rs
+++ b/src/libstd/rt/join_latch.rs
@@ -583,29 +583,31 @@ mod test {
         }
     }
 
+    #[deriving(Clone)]
+    struct Order {
+        immediate: bool,
+        succeed: bool,
+        orders: ~[Order]
+    }
+
     #[test]
     fn whateverman() {
-        struct Order {
-            immediate: bool,
-            succeed: bool,
-            orders: ~[Order]
-        }
         fn next(latch: &mut JoinLatch, orders: ~[Order]) {
             for orders.iter().advance |order| {
-                let suborders = copy order.orders;
+                let suborders = order.orders.clone();
                 let child_latch = Cell::new(latch.new_child());
                 let succeed = order.succeed;
                 if order.immediate {
                     do spawntask_immediately {
                         let mut child_latch = child_latch.take();
-                        next(&mut *child_latch, copy suborders);
+                        next(&mut *child_latch, suborders.clone());
                         rtdebug!("immediate releasing");
                         child_latch.release(succeed);
                     }
                 } else {
                     do spawntask_later {
                         let mut child_latch = child_latch.take();
-                        next(&mut *child_latch, copy suborders);
+                        next(&mut *child_latch, suborders.clone());
                         rtdebug!("later releasing");
                         child_latch.release(succeed);
                     }
diff --git a/src/libstd/run.rs b/src/libstd/run.rs
index 883870db1e6..d2c308c07ea 100644
--- a/src/libstd/run.rs
+++ b/src/libstd/run.rs
@@ -13,6 +13,7 @@
 #[allow(missing_doc)];
 
 use cast;
+use clone::Clone;
 use comm::{stream, SharedChan, GenericChan, GenericPort};
 use io;
 use iterator::IteratorUtil;
@@ -698,7 +699,7 @@ fn with_argv<T>(prog: &str, args: &[~str],
     let mut argptrs = ~[str::as_c_str(prog, |b| b)];
     let mut tmps = ~[];
     for args.iter().advance |arg| {
-        let t = @copy *arg;
+        let t = @(*arg).clone();
         tmps.push(t);
         argptrs.push(str::as_c_str(*t, |b| b));
     }
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index bc3015685bb..0811dab407e 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -2260,6 +2260,13 @@ impl Clone for ~str {
     }
 }
 
+impl Clone for @str {
+    #[inline]
+    fn clone(&self) -> @str {
+        *self
+    }
+}
+
 /// External iterator for a string's characters. Use with the `std::iterator`
 /// module.
 pub struct StrCharIterator<'self> {
@@ -3210,7 +3217,7 @@ mod tests {
                 0x000a_u16 ]) ];
 
         for pairs.iter().advance |p| {
-            let (s, u) = copy *p;
+            let (s, u) = (*p).clone();
             assert!(s.to_utf16() == u);
             assert!(from_utf16(u) == s);
             assert!(from_utf16(s.to_utf16()) == s);
diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs
index 45702546278..841be4df6e2 100644
--- a/src/libstd/tuple.rs
+++ b/src/libstd/tuple.rs
@@ -12,6 +12,7 @@
 
 #[allow(missing_doc)];
 
+use clone::Clone;
 use kinds::Copy;
 use vec;
 use vec::ImmutableVector;
@@ -19,7 +20,7 @@ use iterator::IteratorUtil;
 
 pub use self::inner::*;
 
-/// Method extensions to pairs where both types satisfy the `Copy` bound
+/// Method extensions to pairs where both types satisfy the `Clone` bound
 pub trait CopyableTuple<T, U> {
     /// Return the first element of self
     fn first(&self) -> T;
@@ -29,12 +30,12 @@ pub trait CopyableTuple<T, U> {
     fn swap(&self) -> (U, T);
 }
 
-impl<T:Copy,U:Copy> CopyableTuple<T, U> for (T, U) {
+impl<T:Clone,U:Clone> CopyableTuple<T, U> for (T, U) {
     /// Return the first element of self
     #[inline]
     fn first(&self) -> T {
         match *self {
-            (ref t, _) => copy *t,
+            (ref t, _) => (*t).clone(),
         }
     }
 
@@ -42,21 +43,21 @@ impl<T:Copy,U:Copy> CopyableTuple<T, U> for (T, U) {
     #[inline]
     fn second(&self) -> U {
         match *self {
-            (_, ref u) => copy *u,
+            (_, ref u) => (*u).clone(),
         }
     }
 
     /// Return the results of swapping the two elements of self
     #[inline]
     fn swap(&self) -> (U, T) {
-        match copy *self {
+        match (*self).clone() {
             (t, u) => (u, t),
         }
     }
 }
 
 /// Method extensions for pairs where the types don't necessarily satisfy the
-/// `Copy` bound
+/// `Clone` bound
 pub trait ImmutableTuple<T, U> {
     /// Return a reference to the first element of self
     fn first_ref<'a>(&'a self) -> &'a T;
@@ -84,7 +85,11 @@ pub trait ExtendedTupleOps<A,B> {
     fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C];
 }
 
-impl<'self,A:Copy,B:Copy> ExtendedTupleOps<A,B> for (&'self [A], &'self [B]) {
+impl<'self,
+     A:Copy + Clone,
+     B:Copy + Clone>
+     ExtendedTupleOps<A,B> for
+     (&'self [A], &'self [B]) {
     #[inline]
     fn zip(&self) -> ~[(A, B)] {
         match *self {
@@ -104,7 +109,10 @@ impl<'self,A:Copy,B:Copy> ExtendedTupleOps<A,B> for (&'self [A], &'self [B]) {
     }
 }
 
-impl<A:Copy,B:Copy> ExtendedTupleOps<A,B> for (~[A], ~[B]) {
+impl<A:Copy + Clone,
+     B:Copy + Clone>
+     ExtendedTupleOps<A,B> for
+     (~[A], ~[B]) {
     #[inline]
     fn zip(&self) -> ~[(A, B)] {
         match *self {
diff --git a/src/libstd/util.rs b/src/libstd/util.rs
index fd29d7dc14b..8e7efeb532a 100644
--- a/src/libstd/util.rs
+++ b/src/libstd/util.rs
@@ -127,6 +127,8 @@ pub fn unreachable() -> ! {
 #[cfg(test)]
 mod tests {
     use super::*;
+
+    use clone::Clone;
     use option::{None, Some};
     use either::{Either, Left, Right};
     use sys::size_of;
@@ -136,8 +138,8 @@ mod tests {
     fn identity_crisis() {
         // Writing a test for the identity function. How did it come to this?
         let x = ~[(5, false)];
-        //FIXME #3387 assert!(x.eq(id(copy x)));
-        let y = copy x;
+        //FIXME #3387 assert!(x.eq(id(x.clone())));
+        let y = x.clone();
         assert!(x.eq(&id(y)));
     }
 
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index c728d4a60f1..c9c5217ca61 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -14,12 +14,11 @@
 
 use cast::transmute;
 use cast;
+use clone::Clone;
 use container::{Container, Mutable};
-use cmp;
 use cmp::{Eq, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
-use clone::Clone;
+use cmp;
 use iterator::*;
-use kinds::Copy;
 use libc::c_void;
 use num::Zero;
 use option::{None, Option, Some};
@@ -72,7 +71,7 @@ pub fn from_fn<T>(n_elts: uint, op: &fn(uint) -> T) -> ~[T] {
  * Creates an owned vector of size `n_elts` and initializes the elements
  * to the value `t`.
  */
-pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> ~[T] {
+pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> ~[T] {
     // FIXME (#7136): manually inline from_fn for 2x plus speedup (sadly very
     // important, from_elem is a bottleneck in borrowck!). Unfortunately it
     // still is substantially slower than using the unsafe
@@ -82,7 +81,7 @@ pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> ~[T] {
         do v.as_mut_buf |p, _len| {
             let mut i = 0u;
             while i < n_elts {
-                intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)), copy t);
+                intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)), t.clone());
                 i += 1u;
             }
         }
@@ -241,7 +240,7 @@ impl<'self, T> Iterator<&'self [T]> for VecRSplitIterator<'self, T> {
 /// Iterates over the `rhs` vector, copying each element and appending it to the
 /// `lhs`. Afterwards, the `lhs` is then returned for use again.
 #[inline]
-pub fn append<T:Copy>(lhs: ~[T], rhs: &[T]) -> ~[T] {
+pub fn append<T:Clone>(lhs: ~[T], rhs: &[T]) -> ~[T] {
     let mut v = lhs;
     v.push_all(rhs);
     v
@@ -269,16 +268,16 @@ pub fn flat_map<T, U>(v: &[T], f: &fn(t: &T) -> ~[U]) -> ~[U] {
 }
 
 /// Flattens a vector of vectors of T into a single vector of T.
-pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] { v.concat_vec() }
+pub fn concat<T:Clone>(v: &[~[T]]) -> ~[T] { v.concat_vec() }
 
 /// Concatenate a vector of vectors, placing a given separator between each
-pub fn connect<T:Copy>(v: &[~[T]], sep: &T) -> ~[T] { v.connect_vec(sep) }
+pub fn connect<T:Clone>(v: &[~[T]], sep: &T) -> ~[T] { v.connect_vec(sep) }
 
 /// Flattens a vector of vectors of T into a single vector of T.
-pub fn concat_slices<T:Copy>(v: &[&[T]]) -> ~[T] { v.concat_vec() }
+pub fn concat_slices<T:Clone>(v: &[&[T]]) -> ~[T] { v.concat_vec() }
 
 /// Concatenate a vector of vectors, placing a given separator between each
-pub fn connect_slices<T:Copy>(v: &[&[T]], sep: &T) -> ~[T] { v.connect_vec(sep) }
+pub fn connect_slices<T:Clone>(v: &[&[T]], sep: &T) -> ~[T] { v.connect_vec(sep) }
 
 #[allow(missing_doc)]
 pub trait VectorVector<T> {
@@ -288,10 +287,10 @@ pub trait VectorVector<T> {
     pub fn connect_vec(&self, sep: &T) -> ~[T];
 }
 
-impl<'self, T:Copy> VectorVector<T> for &'self [~[T]] {
+impl<'self, T:Clone> VectorVector<T> for &'self [~[T]] {
     /// Flattens a vector of slices of T into a single vector of T.
     pub fn concat_vec(&self) -> ~[T] {
-        self.flat_map(|inner| copy *inner)
+        self.flat_map(|inner| (*inner).clone())
     }
 
     /// Concatenate a vector of vectors, placing a given separator between each.
@@ -299,14 +298,14 @@ impl<'self, T:Copy> VectorVector<T> for &'self [~[T]] {
         let mut r = ~[];
         let mut first = true;
         for self.iter().advance |inner| {
-            if first { first = false; } else { r.push(copy *sep); }
-            r.push_all(copy *inner);
+            if first { first = false; } else { r.push((*sep).clone()); }
+            r.push_all((*inner).clone());
         }
         r
     }
 }
 
-impl<'self, T:Copy> VectorVector<T> for &'self [&'self [T]] {
+impl<'self,T:Clone> VectorVector<T> for &'self [&'self [T]] {
     /// Flattens a vector of slices of T into a single vector of T.
     pub fn concat_vec(&self) -> ~[T] {
         self.flat_map(|&inner| inner.to_owned())
@@ -317,7 +316,7 @@ impl<'self, T:Copy> VectorVector<T> for &'self [&'self [T]] {
         let mut r = ~[];
         let mut first = true;
         for self.iter().advance |&inner| {
-            if first { first = false; } else { r.push(copy *sep); }
+            if first { first = false; } else { r.push((*sep).clone()); }
             r.push_all(inner);
         }
         r
@@ -331,11 +330,11 @@ impl<'self, T:Copy> VectorVector<T> for &'self [&'self [T]] {
 /**
  * Convert a vector of pairs into a pair of vectors, by reference. As unzip().
  */
-pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) {
+pub fn unzip_slice<T:Clone,U:Clone>(v: &[(T, U)]) -> (~[T], ~[U]) {
     let mut ts = ~[];
     let mut us = ~[];
     for v.iter().advance |p| {
-        let (t, u) = copy *p;
+        let (t, u) = (*p).clone();
         ts.push(t);
         us.push(u);
     }
@@ -364,14 +363,13 @@ pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) {
 /**
  * Convert two vectors to a vector of pairs, by reference. As zip().
  */
-pub fn zip_slice<T:Copy,U:Copy>(v: &[T], u: &[U])
-        -> ~[(T, U)] {
+pub fn zip_slice<T:Clone,U:Clone>(v: &[T], u: &[U]) -> ~[(T, U)] {
     let mut zipped = ~[];
     let sz = v.len();
     let mut i = 0u;
     assert_eq!(sz, u.len());
     while i < sz {
-        zipped.push((copy v[i], copy u[i]));
+        zipped.push((v[i].clone(), u[i].clone()));
         i += 1u;
     }
     zipped
@@ -415,9 +413,9 @@ pub fn zip<T, U>(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] {
  *
  *  * `fun` - The function to iterate over the combinations
  */
-pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool {
+pub fn each_permutation<T:Clone>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool {
     let length = values.len();
-    let mut permutation = vec::from_fn(length, |i| copy values[i]);
+    let mut permutation = vec::from_fn(length, |i| values[i].clone());
     if length <= 1 {
         fun(permutation);
         return true;
@@ -444,7 +442,7 @@ pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) ->
         indices.mut_slice(k+1, length).reverse();
         // fixup permutation based on indices
         for uint::range(k, length) |i| {
-            permutation[i] = copy values[indices[i]];
+            permutation[i] = values[indices[i]].clone();
         }
     }
 }
@@ -496,7 +494,8 @@ impl<'self, T> Iterator<&'self [T]> for VecChunkIter<'self, T> {
 #[cfg(not(test))]
 pub mod traits {
     use super::Vector;
-    use kinds::Copy;
+
+    use clone::Clone;
     use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Equal, Equiv};
     use ops::Add;
 
@@ -615,7 +614,7 @@ pub mod traits {
         fn gt(&self, other: &@[T]) -> bool { self.as_slice() > other.as_slice() }
     }
 
-    impl<'self,T:Copy, V: Vector<T>> Add<V, ~[T]> for &'self [T] {
+    impl<'self,T:Clone, V: Vector<T>> Add<V, ~[T]> for &'self [T] {
         #[inline]
         fn add(&self, rhs: &V) -> ~[T] {
             let mut res = self.to_owned();
@@ -623,7 +622,7 @@ pub mod traits {
             res
         }
     }
-    impl<T:Copy, V: Vector<T>> Add<V, ~[T]> for ~[T] {
+    impl<T:Clone, V: Vector<T>> Add<V, ~[T]> for ~[T] {
         #[inline]
         fn add(&self, rhs: &V) -> ~[T] {
             let mut res = self.to_owned();
@@ -688,13 +687,13 @@ pub trait CopyableVector<T> {
 }
 
 /// Extension methods for vectors
-impl<'self,T:Copy> CopyableVector<T> for &'self [T] {
+impl<'self,T:Clone> CopyableVector<T> for &'self [T] {
     /// Returns a copy of `v`.
     #[inline]
     fn to_owned(&self) -> ~[T] {
         let mut result = with_capacity(self.len());
         for self.iter().advance |e| {
-            result.push(copy *e);
+            result.push((*e).clone());
         }
         result
     }
@@ -927,6 +926,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
     fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U] {
         flat_map(*self, f)
     }
+
     /// Returns a pointer to the element at the given index, without doing
     /// bounds checking.
     #[inline]
@@ -1044,7 +1044,7 @@ pub trait ImmutableCopyableVector<T> {
 }
 
 /// Extension methods for vectors
-impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] {
+impl<'self,T:Clone> ImmutableCopyableVector<T> for &'self [T] {
     /**
      * Partitions the vector into those that satisfies the predicate, and
      * those that do not.
@@ -1056,9 +1056,9 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] {
 
         for self.iter().advance |elt| {
             if f(elt) {
-                lefts.push(copy *elt);
+                lefts.push((*elt).clone());
             } else {
-                rights.push(copy *elt);
+                rights.push((*elt).clone());
             }
         }
 
@@ -1068,7 +1068,7 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] {
     /// Returns the element at the given index, without doing bounds checking.
     #[inline]
     unsafe fn unsafe_get(&self, index: uint) -> T {
-        copy *self.unsafe_ref(index)
+        (*self.unsafe_ref(index)).clone()
     }
 }
 
@@ -1555,13 +1555,13 @@ impl<T> Mutable for ~[T] {
 }
 
 #[allow(missing_doc)]
-pub trait OwnedCopyableVector<T:Copy> {
+pub trait OwnedCopyableVector<T:Clone> {
     fn push_all(&mut self, rhs: &[T]);
     fn grow(&mut self, n: uint, initval: &T);
     fn grow_set(&mut self, index: uint, initval: &T, val: T);
 }
 
-impl<T:Copy> OwnedCopyableVector<T> for ~[T] {
+impl<T:Clone> OwnedCopyableVector<T> for ~[T] {
     /// Iterates over the slice `rhs`, copies each element, and then appends it to
     /// the vector provided `v`. The `rhs` vector is traversed in-order.
     ///
@@ -1596,7 +1596,7 @@ impl<T:Copy> OwnedCopyableVector<T> for ~[T] {
         let mut i: uint = 0u;
 
         while i < n {
-            self.push(copy *initval);
+            self.push((*initval).clone());
             i += 1u;
         }
     }
@@ -1894,7 +1894,7 @@ pub struct UnboxedVecRepr {
 /// Unsafe operations
 pub mod raw {
     use cast::transmute;
-    use kinds::Copy;
+    use clone::Clone;
     use managed;
     use option::{None, Some};
     use ptr;
@@ -2009,8 +2009,8 @@ pub mod raw {
      * Unchecked vector indexing.
      */
     #[inline]
-    pub unsafe fn get<T:Copy>(v: &[T], i: uint) -> T {
-        v.as_imm_buf(|p, _len| copy *ptr::offset(p, i))
+    pub unsafe fn get<T:Clone>(v: &[T], i: uint) -> T {
+        v.as_imm_buf(|p, _len| (*ptr::offset(p, i)).clone())
     }
 
     /**
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs
index fadd2faf0eb..bf0dee0822f 100644
--- a/src/libsyntax/abi.rs
+++ b/src/libsyntax/abi.rs
@@ -58,7 +58,7 @@ enum AbiArchitecture {
     Archs(u32)  // Multiple architectures (bitset)
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Clone, Eq, Encodable, Decodable)]
 pub struct AbiSet {
     priv bits: u32   // each bit represents one of the abis below
 }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 6cf38d5ae1d..38f0b2496cb 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -24,7 +24,7 @@ use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
 // table) and a SyntaxContext to track renaming and
 // macro expansion per Flatt et al., "Macros
 // That Work Together"
-#[deriving(Eq,IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct ident { name: Name, ctxt: SyntaxContext }
 
 /// Construct an identifier with the given name and an empty context:
@@ -93,7 +93,7 @@ impl<D:Decoder> Decodable<D> for ident {
 // Functions may or may not have names.
 pub type fn_ident = Option<ident>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct Lifetime {
     id: node_id,
     span: span,
@@ -104,7 +104,7 @@ pub struct Lifetime {
 // for instance: core::cmp::Eq  .  It's represented
 // as a sequence of identifiers, along with a bunch
 // of supporting information.
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct Path {
     span: span,
     global: bool,
@@ -117,7 +117,7 @@ pub type crate_num = int;
 
 pub type node_id = int;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct def_id {
     crate: crate_num,
     node: node_id,
@@ -126,27 +126,27 @@ pub struct def_id {
 pub static local_crate: crate_num = 0;
 pub static crate_node_id: node_id = 0;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
 // The AST represents all type param bounds as types.
 // typeck::collect::compute_bounds matches these against
 // the "special" built-in traits (see middle::lang_items) and
 // detects Copy, Send, Send, and Freeze.
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum TyParamBound {
     TraitTyParamBound(trait_ref),
     RegionTyParamBound
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct TyParam {
     ident: ident,
     id: node_id,
     bounds: OptVec<TyParamBound>
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct Generics {
     lifetimes: OptVec<Lifetime>,
-    ty_params: OptVec<TyParam>
+    ty_params: OptVec<TyParam>,
 }
 
 impl Generics {
@@ -161,7 +161,7 @@ impl Generics {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum def {
     def_fn(def_id, purity),
     def_static_method(/* method */ def_id,
@@ -199,7 +199,7 @@ pub type crate_cfg = ~[@meta_item];
 
 pub type crate = spanned<crate_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct crate_ {
     module: _mod,
     attrs: ~[attribute],
@@ -208,7 +208,7 @@ pub struct crate_ {
 
 pub type meta_item = spanned<meta_item_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum meta_item_ {
     meta_word(@str),
     meta_list(@str, ~[@meta_item]),
@@ -217,7 +217,7 @@ pub enum meta_item_ {
 
 //pub type blk = spanned<blk_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
 pub struct blk {
     view_items: ~[view_item],
     stmts: ~[@stmt],
@@ -227,26 +227,26 @@ pub struct blk {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct pat {
     id: node_id,
     node: pat_,
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct field_pat {
     ident: ident,
     pat: @pat,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum binding_mode {
     bind_by_ref(mutability),
     bind_infer
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum pat_ {
     pat_wild,
     // A pat_ident may either be a new bound variable,
@@ -271,10 +271,10 @@ pub enum pat_ {
     pat_vec(~[@pat], Option<@pat>, ~[@pat])
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum mutability { m_mutbl, m_imm, m_const, }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum Sigil {
     BorrowedSigil,
     OwnedSigil,
@@ -300,7 +300,7 @@ pub enum vstore {
     vstore_slice(Option<Lifetime>) // &'foo? [1,2,3,4]
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum expr_vstore {
     expr_vstore_uniq,                  // ~[1,2,3,4]
     expr_vstore_box,                   // @[1,2,3,4]
@@ -309,7 +309,7 @@ pub enum expr_vstore {
     expr_vstore_mut_slice,             // &mut [1,2,3,4]
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum binop {
     add,
     subtract,
@@ -331,7 +331,7 @@ pub enum binop {
     gt,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum unop {
     box(mutability),
     uniq,
@@ -342,7 +342,7 @@ pub enum unop {
 
 pub type stmt = spanned<stmt_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum stmt_ {
     // could be an item or a local (let) binding:
     stmt_decl(@decl, node_id),
@@ -380,14 +380,14 @@ pub enum decl_ {
     decl_item(@item),
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct arm {
     pats: ~[@pat],
     guard: Option<@expr>,
     body: blk,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct field_ {
     ident: ident,
     expr: @expr,
@@ -395,8 +395,11 @@ pub struct field_ {
 
 pub type field = spanned<field_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
-pub enum blk_check_mode { default_blk, unsafe_blk, }
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
+pub enum blk_check_mode {
+    default_blk,
+    unsafe_blk,
+}
 
 #[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct expr {
@@ -418,14 +421,14 @@ impl expr {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum CallSugar {
     NoSugar,
     DoSugar,
     ForSugar
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum expr_ {
     expr_vstore(@expr, expr_vstore),
     expr_vec(~[@expr], mutability),
@@ -496,7 +499,7 @@ pub enum expr_ {
 // else knows what to do with them, so you'll probably get a syntax
 // error.
 //
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 #[doc="For macro invocations; parsing is delegated to the macro"]
 pub enum token_tree {
     // a single token
@@ -569,7 +572,7 @@ pub enum token_tree {
 //
 pub type matcher = spanned<matcher_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum matcher_ {
     // match one token
     match_tok(::parse::token::Token),
@@ -582,14 +585,14 @@ pub enum matcher_ {
 
 pub type mac = spanned<mac_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum mac_ {
     mac_invoc_tt(Path,~[token_tree]),   // new macro-invocation
 }
 
 pub type lit = spanned<lit_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum lit_ {
     lit_str(@str),
     lit_int(i64, int_ty),
@@ -603,7 +606,7 @@ pub enum lit_ {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct mt {
     ty: ~Ty,
     mutbl: mutability,
@@ -617,7 +620,7 @@ pub struct ty_field_ {
 
 pub type ty_field = spanned<ty_field_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct ty_method {
     ident: ident,
     attrs: ~[attribute],
@@ -629,17 +632,24 @@ pub struct ty_method {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
 // A trait method is either required (meaning it doesn't have an
 // implementation, just a signature) or provided (meaning it has a default
 // implementation).
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum trait_method {
     required(ty_method),
     provided(@method),
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
-pub enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
+pub enum int_ty {
+    ty_i,
+    ty_char,
+    ty_i8,
+    ty_i16,
+    ty_i32,
+    ty_i64,
+}
 
 impl ToStr for int_ty {
     fn to_str(&self) -> ~str {
@@ -647,8 +657,14 @@ impl ToStr for int_ty {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
-pub enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, }
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
+pub enum uint_ty {
+    ty_u,
+    ty_u8,
+    ty_u16,
+    ty_u32,
+    ty_u64,
+}
 
 impl ToStr for uint_ty {
     fn to_str(&self) -> ~str {
@@ -656,8 +672,12 @@ impl ToStr for uint_ty {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
-pub enum float_ty { ty_f, ty_f32, ty_f64, }
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
+pub enum float_ty {
+    ty_f,
+    ty_f32,
+    ty_f64,
+}
 
 impl ToStr for float_ty {
     fn to_str(&self) -> ~str {
@@ -666,7 +686,7 @@ impl ToStr for float_ty {
 }
 
 // NB Eq method appears below.
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
 pub struct Ty {
     id: node_id,
     node: ty_,
@@ -674,7 +694,7 @@ pub struct Ty {
 }
 
 // Not represented directly in the AST, referred to by name through a ty_path.
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum prim_ty {
     ty_int(int_ty),
     ty_uint(uint_ty),
@@ -683,7 +703,7 @@ pub enum prim_ty {
     ty_bool,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum Onceness {
     Once,
     Many
@@ -722,7 +742,7 @@ pub struct TyBareFn {
     decl: fn_decl
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum ty_ {
     ty_nil,
     ty_bot, /* bottom type */
@@ -743,13 +763,13 @@ pub enum ty_ {
     ty_infer,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum asm_dialect {
     asm_att,
     asm_intel
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct inline_asm {
     asm: @str,
     clobbers: @str,
@@ -760,7 +780,7 @@ pub struct inline_asm {
     dialect: asm_dialect
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct arg {
     is_mutbl: bool,
     ty: Ty,
@@ -768,14 +788,14 @@ pub struct arg {
     id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct fn_decl {
     inputs: ~[arg],
     output: Ty,
     cf: ret_style,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum purity {
     unsafe_fn, // declared with "unsafe fn"
     impure_fn, // declared with "fn"
@@ -793,14 +813,14 @@ impl ToStr for purity {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum ret_style {
     noreturn, // functions with return type _|_ that always
               // raise an error or exit (i.e. never return to the caller)
     return_val, // everything else
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum explicit_self_ {
     sty_static,                                // no self
     sty_value,                                 // `self`
@@ -826,17 +846,20 @@ pub struct method {
     vis: visibility,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct _mod {
     view_items: ~[view_item],
     items: ~[@item],
 }
 
 // Foreign mods can be named or anonymous
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
-pub enum foreign_mod_sort { named, anonymous }
+#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
+pub enum foreign_mod_sort {
+    named,
+    anonymous,
+}
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
 pub struct foreign_mod {
     sort: foreign_mod_sort,
     abis: AbiSet,
@@ -844,24 +867,24 @@ pub struct foreign_mod {
     items: ~[@foreign_item],
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct variant_arg {
     ty: Ty,
     id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum variant_kind {
     tuple_variant_kind(~[variant_arg]),
     struct_variant_kind(@struct_def),
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct enum_def {
     variants: ~[variant],
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct variant_ {
     name: ident,
     attrs: ~[attribute],
@@ -873,7 +896,7 @@ pub struct variant_ {
 
 pub type variant = spanned<variant_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct path_list_ident_ {
     name: ident,
     id: node_id,
@@ -883,7 +906,7 @@ pub type path_list_ident = spanned<path_list_ident_>;
 
 pub type view_path = spanned<view_path_>;
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Eq, Encodable, Decodable, IterBytes)]
 pub enum view_path_ {
 
     // quux = foo::bar::baz
@@ -900,7 +923,7 @@ pub enum view_path_ {
     view_path_list(Path, ~[path_list_ident], node_id)
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct view_item {
     node: view_item_,
     attrs: ~[attribute],
@@ -908,7 +931,7 @@ pub struct view_item {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum view_item_ {
     view_item_extern_mod(ident, ~[@meta_item], node_id),
     view_item_use(~[@view_path]),
@@ -920,11 +943,14 @@ pub type attribute = spanned<attribute_>;
 // Distinguishes between attributes that decorate items and attributes that
 // are contained as statements within items. These two cases need to be
 // distinguished for pretty-printing.
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
-pub enum attr_style { attr_outer, attr_inner, }
+#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
+pub enum attr_style {
+    attr_outer,
+    attr_inner,
+}
 
 // doc-comments are promoted to attributes that have is_sugared_doc = true
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
 pub struct attribute_ {
     style: attr_style,
     value: @meta_item,
@@ -938,14 +964,18 @@ pub struct attribute_ {
   If this impl is an item_impl, the impl_id is redundant (it could be the
   same as the impl's node id).
  */
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
 pub struct trait_ref {
     path: Path,
     ref_id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
-pub enum visibility { public, private, inherited }
+#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
+pub enum visibility {
+    public,
+    private,
+    inherited,
+}
 
 impl visibility {
     pub fn inherit_from(&self, parent_visibility: visibility) -> visibility {
@@ -984,7 +1014,7 @@ pub struct struct_def {
   FIXME (#3300): Should allow items to be anonymous. Right now
   we just use dummy names for anon items.
  */
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct item {
     ident: ident,
     attrs: ~[attribute],
@@ -994,7 +1024,7 @@ pub struct item {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum item_ {
     item_static(Ty, mutability, @expr),
     item_fn(fn_decl, purity, AbiSet, Generics, blk),
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 354471fc2a1..721f5108cc0 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -24,31 +24,12 @@ use std::cmp;
 use std::hashmap::HashMap;
 use std::vec;
 
+#[deriving(Clone, Eq)]
 pub enum path_elt {
     path_mod(ident),
     path_name(ident)
 }
 
-impl cmp::Eq for path_elt {
-    fn eq(&self, other: &path_elt) -> bool {
-        match (*self) {
-            path_mod(e0a) => {
-                match (*other) {
-                    path_mod(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            path_name(e0a) => {
-                match (*other) {
-                    path_name(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-        }
-    }
-    fn ne(&self, other: &path_elt) -> bool { !(*self).eq(other) }
-}
-
 pub type path = ~[path_elt];
 
 pub fn path_to_str_with_sep(p: &[path_elt], sep: &str, itr: @ident_interner)
@@ -64,7 +45,6 @@ pub fn path_to_str_with_sep(p: &[path_elt], sep: &str, itr: @ident_interner)
 
 pub fn path_ident_to_str(p: &path, i: ident, itr: @ident_interner) -> ~str {
     if p.is_empty() {
-        //FIXME /* FIXME (#2543) */ copy *i
         itr.get(i.name).to_owned()
     } else {
         fmt!("%s::%s", path_to_str(*p, itr), itr.get(i.name))
@@ -82,6 +62,7 @@ pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
     }
 }
 
+#[deriving(Clone)]
 pub enum ast_node {
     node_item(@item, @path),
     node_foreign_item(@foreign_item, AbiSet, visibility, @path),
@@ -109,7 +90,7 @@ pub struct Ctx {
 pub type vt = visit::vt<@mut Ctx>;
 
 pub fn extend(cx: @mut Ctx, elt: ident) -> @path {
-    @(vec::append(copy cx.path, [path_name(elt)]))
+    @(vec::append(cx.path.clone(), [path_name(elt)]))
 }
 
 pub fn mk_ast_map_visitor() -> vt {
@@ -149,7 +130,7 @@ pub fn map_decoded_item(diag: @span_handler,
     // variables that are simultaneously in scope).
     let cx = @mut Ctx {
         map: map,
-        path: copy path,
+        path: path.clone(),
         diag: diag,
     };
     let v = mk_ast_map_visitor();
@@ -190,7 +171,7 @@ pub fn map_fn(
 }
 
 pub fn map_block(b: &blk, (cx,v): (@mut Ctx, visit::vt<@mut Ctx>)) {
-    cx.map.insert(b.id, node_block(/* FIXME (#2543) */ copy *b));
+    cx.map.insert(b.id, node_block(/* FIXME (#2543) */ (*b).clone()));
     visit::visit_block(b, (cx, v));
 }
 
@@ -216,7 +197,7 @@ pub fn map_method(impl_did: def_id, impl_path: @path,
 }
 
 pub fn map_item(i: @item, (cx, v): (@mut Ctx, visit::vt<@mut Ctx>)) {
-    let item_path = @/* FIXME (#2543) */ copy cx.path;
+    let item_path = @/* FIXME (#2543) */ cx.path.clone();
     cx.map.insert(i.id, node_item(i, item_path));
     match i.node {
         item_impl(_, _, _, ref ms) => {
@@ -228,7 +209,8 @@ pub fn map_item(i: @item, (cx, v): (@mut Ctx, visit::vt<@mut Ctx>)) {
         item_enum(ref enum_definition, _) => {
             for (*enum_definition).variants.iter().advance |v| {
                 cx.map.insert(v.node.id, node_variant(
-                    /* FIXME (#2543) */ copy *v, i,
+                    /* FIXME (#2543) */ (*v).clone(),
+                    i,
                     extend(cx, i.ident)));
             }
         }
@@ -251,7 +233,7 @@ pub fn map_item(i: @item, (cx, v): (@mut Ctx, visit::vt<@mut Ctx>)) {
                             extend(cx, i.ident)
                         } else {
                             // Anonymous extern mods go in the parent scope
-                            @copy cx.path
+                            @cx.path.clone()
                         }
                     )
                 );
@@ -275,7 +257,7 @@ pub fn map_item(i: @item, (cx, v): (@mut Ctx, visit::vt<@mut Ctx>)) {
                 let d_id = ast_util::local_def(i.id);
                 cx.map.insert(
                     id,
-                    node_trait_method(@copy *tm, d_id, item_path)
+                    node_trait_method(@(*tm).clone(), d_id, item_path)
                 );
             }
         }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index feadf3fdbf3..843fd4bdba2 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -238,7 +238,11 @@ pub fn is_unguarded(a: &arm) -> bool {
 }
 
 pub fn unguarded_pat(a: &arm) -> Option<~[@pat]> {
-    if is_unguarded(a) { Some(/* FIXME (#2543) */ copy a.pats) } else { None }
+    if is_unguarded(a) {
+        Some(/* FIXME (#2543) */ a.pats.clone())
+    } else {
+        None
+    }
 }
 
 pub fn public_methods(ms: ~[@method]) -> ~[@method] {
@@ -254,14 +258,14 @@ pub fn public_methods(ms: ~[@method]) -> ~[@method] {
 // a default, pull out the useful fields to make a ty_method
 pub fn trait_method_to_ty_method(method: &trait_method) -> ty_method {
     match *method {
-        required(ref m) => copy *m,
+        required(ref m) => (*m).clone(),
         provided(ref m) => {
             ty_method {
                 ident: m.ident,
-                attrs: copy m.attrs,
+                attrs: m.attrs.clone(),
                 purity: m.purity,
-                decl: copy m.decl,
-                generics: copy m.generics,
+                decl: m.decl.clone(),
+                generics: m.generics.clone(),
                 explicit_self: m.explicit_self,
                 id: m.id,
                 span: m.span,
@@ -276,7 +280,7 @@ pub fn split_trait_methods(trait_methods: &[trait_method])
     let mut provd = ~[];
     for trait_methods.iter().advance |trt_method| {
         match *trt_method {
-          required(ref tm) => reqd.push(copy *tm),
+          required(ref tm) => reqd.push((*tm).clone()),
           provided(m) => provd.push(m)
         }
     };
@@ -293,7 +297,7 @@ pub fn struct_field_visibility(field: ast::struct_field) -> visibility {
 pub trait inlined_item_utils {
     fn ident(&self) -> ident;
     fn id(&self) -> ast::node_id;
-    fn accept<E: Copy>(&self, e: E, v: visit::vt<E>);
+    fn accept<E: Clone>(&self, e: E, v: visit::vt<E>);
 }
 
 impl inlined_item_utils for inlined_item {
@@ -313,7 +317,7 @@ impl inlined_item_utils for inlined_item {
         }
     }
 
-    fn accept<E: Copy>(&self, e: E, v: visit::vt<E>) {
+    fn accept<E: Clone>(&self, e: E, v: visit::vt<E>) {
         match *self {
             ii_item(i) => (v.visit_item)(i, (e, v)),
             ii_foreign(i) => (v.visit_foreign_item)(i, (e, v)),
@@ -385,33 +389,33 @@ impl id_range {
     }
 }
 
-pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
+pub fn id_visitor<T: Clone>(vfn: @fn(node_id, T)) -> visit::vt<T> {
     let visit_generics: @fn(&Generics, T) = |generics, t| {
         for generics.ty_params.iter().advance |p| {
-            vfn(p.id, copy t);
+            vfn(p.id, t.clone());
         }
         for generics.lifetimes.iter().advance |p| {
-            vfn(p.id, copy t);
+            vfn(p.id, t.clone());
         }
     };
     visit::mk_vt(@visit::Visitor {
-        visit_mod: |m, sp, id, (t, vt)| {
-            vfn(id, copy t);
+        visit_mod: |m, sp, id, (t, vt): (T, visit::vt<T>)| {
+            vfn(id, t.clone());
             visit::visit_mod(m, sp, id, (t, vt));
         },
 
         visit_view_item: |vi, (t, vt)| {
             match vi.node {
-              view_item_extern_mod(_, _, id) => vfn(id, copy t),
+              view_item_extern_mod(_, _, id) => vfn(id, t.clone()),
               view_item_use(ref vps) => {
                   for vps.iter().advance |vp| {
                       match vp.node {
-                          view_path_simple(_, _, id) => vfn(id, copy t),
-                          view_path_glob(_, id) => vfn(id, copy t),
+                          view_path_simple(_, _, id) => vfn(id, t.clone()),
+                          view_path_glob(_, id) => vfn(id, t.clone()),
                           view_path_list(_, ref paths, id) => {
-                              vfn(id, copy t);
+                              vfn(id, t.clone());
                               for paths.iter().advance |p| {
-                                  vfn(p.node.id, copy t);
+                                  vfn(p.node.id, t.clone());
                               }
                           }
                       }
@@ -422,34 +426,36 @@ pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
         },
 
         visit_foreign_item: |ni, (t, vt)| {
-            vfn(ni.id, copy t);
+            vfn(ni.id, t.clone());
             visit::visit_foreign_item(ni, (t, vt));
         },
 
         visit_item: |i, (t, vt)| {
-            vfn(i.id, copy t);
+            vfn(i.id, t.clone());
             match i.node {
               item_enum(ref enum_definition, _) =>
-                for (*enum_definition).variants.iter().advance |v| { vfn(v.node.id, copy t); },
+                for (*enum_definition).variants.iter().advance |v| {
+                    vfn(v.node.id, t.clone());
+                },
               _ => ()
             }
             visit::visit_item(i, (t, vt));
         },
 
         visit_local: |l, (t, vt)| {
-            vfn(l.node.id, copy t);
+            vfn(l.node.id, t.clone());
             visit::visit_local(l, (t, vt));
         },
         visit_block: |b, (t, vt)| {
-            vfn(b.id, copy t);
+            vfn(b.id, t.clone());
             visit::visit_block(b, (t, vt));
         },
         visit_stmt: |s, (t, vt)| {
-            vfn(ast_util::stmt_id(s), copy t);
+            vfn(ast_util::stmt_id(s), t.clone());
             visit::visit_stmt(s, (t, vt));
         },
         visit_pat: |p, (t, vt)| {
-            vfn(p.id, copy t);
+            vfn(p.id, t.clone());
             visit::visit_pat(p, (t, vt));
         },
 
@@ -457,37 +463,37 @@ pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
             {
                 let r = e.get_callee_id();
                 for r.iter().advance |callee_id| {
-                    vfn(*callee_id, copy t);
+                    vfn(*callee_id, t.clone());
                 }
             }
-            vfn(e.id, copy t);
+            vfn(e.id, t.clone());
             visit::visit_expr(e, (t, vt));
         },
 
         visit_ty: |ty, (t, vt)| {
-            vfn(ty.id, copy t);
+            vfn(ty.id, t.clone());
             match ty.node {
-              ty_path(_, _, id) => vfn(id, copy t),
+              ty_path(_, _, id) => vfn(id, t.clone()),
               _ => { /* fall through */ }
             }
             visit::visit_ty(ty, (t, vt));
         },
 
         visit_generics: |generics, (t, vt)| {
-            visit_generics(generics, copy t);
+            visit_generics(generics, t.clone());
             visit::visit_generics(generics, (t, vt));
         },
 
         visit_fn: |fk, d, a, b, id, (t, vt)| {
-            vfn(id, copy t);
+            vfn(id, t.clone());
 
             match *fk {
                 visit::fk_item_fn(_, generics, _, _) => {
-                    visit_generics(generics, copy t);
+                    visit_generics(generics, t.clone());
                 }
                 visit::fk_method(_, generics, m) => {
-                    vfn(m.self_id, copy t);
-                    visit_generics(generics, copy t);
+                    vfn(m.self_id, t.clone());
+                    visit_generics(generics, t.clone());
                 }
                 visit::fk_anon(_) |
                 visit::fk_fn_block => {
@@ -495,13 +501,13 @@ pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
             }
 
             for d.inputs.iter().advance |arg| {
-                vfn(arg.id, copy t)
+                vfn(arg.id, t.clone())
             }
-            visit::visit_fn(fk, d, a, b, id, (copy t, vt));
+            visit::visit_fn(fk, d, a, b, id, (t.clone(), vt));
         },
 
         visit_struct_field: |f, (t, vt)| {
-            vfn(f.node.id, copy t);
+            vfn(f.node.id, t.clone());
             visit::visit_struct_field(f, (t, vt));
         },
 
@@ -800,19 +806,19 @@ mod test {
     #[test] fn xorpush_test () {
         let mut s = ~[];
         xorPush(&mut s,14);
-        assert_eq!(copy s,~[14]);
+        assert_eq!(s.clone(),~[14]);
         xorPush(&mut s,14);
-        assert_eq!(copy s,~[]);
+        assert_eq!(s.clone(),~[]);
         xorPush(&mut s,14);
-        assert_eq!(copy s,~[14]);
+        assert_eq!(s.clone(),~[14]);
         xorPush(&mut s,15);
-        assert_eq!(copy s,~[14,15]);
+        assert_eq!(s.clone(),~[14,15]);
         xorPush (&mut s,16);
-        assert_eq!(copy s,~[14,15,16]);
+        assert_eq!(s.clone(),~[14,15,16]);
         xorPush (&mut s,16);
-        assert_eq!(copy s,~[14,15]);
+        assert_eq!(s.clone(),~[14,15]);
         xorPush (&mut s,15);
-        assert_eq!(copy s,~[14]);
+        assert_eq!(s.clone(),~[14]);
     }
 
     // convert a list of uints to an @[ident]
@@ -868,7 +874,7 @@ mod test {
         let mut t = new_sctable_internal();
 
         let test_sc = ~[M(3),R(id(101,0),14),M(9)];
-        assert_eq!(unfold_test_sc(copy test_sc,empty_ctxt,&mut t),4);
+        assert_eq!(unfold_test_sc(test_sc.clone(),empty_ctxt,&mut t),4);
         assert_eq!(t.table[2],Mark(9,0));
         assert_eq!(t.table[3],Rename(id(101,0),14,2));
         assert_eq!(t.table[4],Mark(3,3));
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 18bef1ea17e..7dd01a54f7a 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -116,7 +116,7 @@ pub fn get_meta_item_value_str(meta: @ast::meta_item) -> Option<@str> {
 pub fn get_meta_item_list(meta: @ast::meta_item)
                        -> Option<~[@ast::meta_item]> {
     match meta.node {
-        ast::meta_list(_, ref l) => Some(/* FIXME (#2543) */ copy *l),
+        ast::meta_list(_, ref l) => Some(/* FIXME (#2543) */ (*l).clone()),
         _ => None
     }
 }
@@ -266,7 +266,7 @@ pub fn sort_meta_items(items: &[@ast::meta_item]) -> ~[@ast::meta_item] {
             ast::meta_list(n, ref mis) => {
                 @spanned {
                     node: ast::meta_list(n, sort_meta_items(*mis)),
-                    .. /*bad*/ copy **m
+                    .. /*bad*/ (**m).clone()
                 }
             }
             _ => *m
@@ -286,7 +286,9 @@ pub fn remove_meta_items_by_name(items: ~[@ast::meta_item], name: &str) ->
 pub fn find_linkage_metas(attrs: &[ast::attribute]) -> ~[@ast::meta_item] {
     do find_attrs_by_name(attrs, "link").flat_map |attr| {
         match attr.node.value.node {
-            ast::meta_list(_, ref items) => /* FIXME (#2543) */ copy *items,
+            ast::meta_list(_, ref items) => {
+                /* FIXME (#2543) */ (*items).clone()
+            }
             _ => ~[]
         }
     }
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index dcd9615ffd0..a9499881cff 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -31,7 +31,7 @@ pub trait Pos {
 }
 
 /// A byte offset
-#[deriving(Eq,IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub struct BytePos(uint);
 /// A character offset. Because of multibyte utf8 characters, a byte offset
 /// is not equivalent to a character offset. The CodeMap will convert BytePos
@@ -96,15 +96,18 @@ are *absolute* positions from the beginning of the codemap, not positions
 relative to FileMaps. Methods on the CodeMap can be used to relate spans back
 to the original source.
 */
-#[deriving(IterBytes)]
+#[deriving(Clone, IterBytes)]
 pub struct span {
     lo: BytePos,
     hi: BytePos,
     expn_info: Option<@ExpnInfo>
 }
 
-#[deriving(Eq, Encodable, Decodable,IterBytes)]
-pub struct spanned<T> { node: T, span: span }
+#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
+pub struct spanned<T> {
+    node: T,
+    span: span,
+}
 
 impl cmp::Eq for span {
     fn eq(&self, other: &span) -> bool {
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 2971ad5cc29..717c5571994 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -265,7 +265,7 @@ fn highlight_lines(cm: @codemap::CodeMap,
     // arbitrarily only print up to six lines of the error
     let max_lines = 6u;
     let mut elided = false;
-    let mut display_lines = /* FIXME (#2543) */ copy lines.lines;
+    let mut display_lines = /* FIXME (#2543) */ lines.lines.clone();
     if display_lines.len() > max_lines {
         display_lines = display_lines.slice(0u, max_lines).to_owned();
         elided = true;
@@ -345,11 +345,11 @@ fn print_macro_backtrace(cm: @codemap::CodeMap, sp: span) {
     }
 }
 
-pub fn expect<T:Copy>(diag: @span_handler,
+pub fn expect<T:Clone>(diag: @span_handler,
                        opt: Option<T>,
                        msg: &fn() -> ~str) -> T {
     match opt {
-       Some(ref t) => copy *t,
-       None => diag.handler().bug(msg())
+       Some(ref t) => (*t).clone(),
+       None => diag.handler().bug(msg()),
     }
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 0e464208de3..e2f37bd54bd 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -238,7 +238,7 @@ impl ExtCtxt {
 
     pub fn codemap(&self) -> @CodeMap { self.parse_sess.cm }
     pub fn parse_sess(&self) -> @mut parse::ParseSess { self.parse_sess }
-    pub fn cfg(&self) -> ast::crate_cfg { copy self.cfg }
+    pub fn cfg(&self) -> ast::crate_cfg { self.cfg.clone() }
     pub fn call_site(&self) -> span {
         match *self.backtrace {
             Some(@ExpnInfo {call_site: cs, _}) => cs,
@@ -249,7 +249,7 @@ impl ExtCtxt {
     pub fn backtrace(&self) -> Option<@ExpnInfo> { *self.backtrace }
     pub fn mod_push(&self, i: ast::ident) { self.mod_path.push(i); }
     pub fn mod_pop(&self) { self.mod_path.pop(); }
-    pub fn mod_path(&self) -> ~[ast::ident] { copy *self.mod_path }
+    pub fn mod_path(&self) -> ~[ast::ident] { (*self.mod_path).clone() }
     pub fn bt_push(&self, ei: codemap::ExpnInfo) {
         match ei {
             ExpnInfo {call_site: cs, callee: ref callee} => {
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 89290b78b72..334721a38ed 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -351,7 +351,7 @@ impl AstBuilder for @ExtCtxt {
         };
         Generics {
             ty_params: new_params,
-            .. copy *generics
+            .. (*generics).clone()
         }
     }
 
@@ -611,13 +611,13 @@ impl AstBuilder for @ExtCtxt {
     }
     fn lambda0(&self, _span: span, blk: ast::blk) -> @ast::expr {
         let ext_cx = *self;
-        let blk_e = self.expr(blk.span, ast::expr_block(copy blk));
+        let blk_e = self.expr(blk.span, ast::expr_block(blk.clone()));
         quote_expr!(|| $blk_e )
     }
 
     fn lambda1(&self, _span: span, blk: ast::blk, ident: ast::ident) -> @ast::expr {
         let ext_cx = *self;
-        let blk_e = self.expr(blk.span, ast::expr_block(copy blk));
+        let blk_e = self.expr(blk.span, ast::expr_block(blk.clone()));
         quote_expr!(|$ident| $blk_e )
     }
 
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index f90ee1f8d79..a50f4d70f0e 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -335,7 +335,7 @@ impl<'self> TraitDef<'self> {
                     cx.typarambound(p.to_path(cx, span, type_ident, generics))
                 });
             // require the current trait
-            bounds.push(cx.typarambound(copy trait_path));
+            bounds.push(cx.typarambound(trait_path.clone()));
 
             trait_generics.ty_params.push(cx.typaram(ty_param.ident, bounds));
         }
@@ -751,7 +751,7 @@ impl<'self> MethodDef<'self> {
                         do self_vec.iter()
                            .zip(enum_matching_fields.iter())
                            .transform |(&(id, self_f), other)| {
-                        (id, self_f, copy *other)
+                        (id, self_f, (*other).clone())
                     }.collect();
                     substructure = EnumMatching(variant_index, variant, field_tuples);
                 }
@@ -789,7 +789,9 @@ impl<'self> MethodDef<'self> {
                                                                     current_match_str,
                                                                     ast::m_imm);
 
-                matches_so_far.push((index, /*bad*/ copy *variant, idents));
+                matches_so_far.push((index,
+                                     /*bad*/ (*variant).clone(),
+                                     idents));
                 let arm_expr = self.build_enum_match(cx, span,
                                                      enum_def,
                                                      type_ident,
@@ -818,7 +820,9 @@ impl<'self> MethodDef<'self> {
                                                                        current_match_str,
                                                                        ast::m_imm);
 
-                    matches_so_far.push((index, /*bad*/ copy *variant, idents));
+                    matches_so_far.push((index,
+                                         /*bad*/ (*variant).clone(),
+                                         idents));
                     let new_matching =
                         match matching {
                             _ if match_count == 0 => Some(index),
@@ -897,7 +901,8 @@ pub fn create_subpatterns(cx: @ExtCtxt,
                           mutbl: ast::mutability)
                    -> ~[@ast::pat] {
     do field_paths.map |path| {
-        cx.pat(span, ast::pat_ident(ast::bind_by_ref(mutbl), copy *path, None))
+        cx.pat(span,
+               ast::pat_ident(ast::bind_by_ref(mutbl), (*path).clone(), None))
     }
 }
 
@@ -944,7 +949,7 @@ fn create_struct_pattern(cx: @ExtCtxt,
         };
         let path = cx.path_ident(span,
                                  cx.ident_of(fmt!("%s_%u", prefix, i)));
-        paths.push(copy path);
+        paths.push(path.clone());
         ident_expr.push((opt_id, cx.expr_path(path)));
     }
 
@@ -990,7 +995,7 @@ fn create_enum_variant_pattern(cx: @ExtCtxt,
                 let path = cx.path_ident(span,
                                          cx.ident_of(fmt!("%s_%u", prefix, i)));
 
-                paths.push(copy path);
+                paths.push(path.clone());
                 ident_expr.push((None, cx.expr_path(path)));
             }
 
@@ -1029,12 +1034,12 @@ pub fn cs_fold(use_foldl: bool,
         EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
             if use_foldl {
                 do all_fields.iter().fold(base) |old, triple| {
-                    let (_, self_f, other_fs) = copy *triple;
+                    let (_, self_f, other_fs) = (*triple).clone();
                     f(cx, span, old, self_f, other_fs)
                 }
             } else {
                 do all_fields.rev_iter().fold(base) |old, triple| {
-                    let (_, self_f, other_fs) = copy *triple;
+                    let (_, self_f, other_fs) = (*triple).clone();
                     f(cx, span, old, self_f, other_fs)
                 }
             }
@@ -1067,7 +1072,7 @@ pub fn cs_same_method(f: &fn(@ExtCtxt, span, ~[@expr]) -> @expr,
         EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
             // call self_n.method(other_1_n, other_2_n, ...)
             let called = do all_fields.map |triple| {
-                let (_, self_field, other_fields) = copy *triple;
+                let (_, self_field, other_fields) = (*triple).clone();
                 cx.expr_method_call(span,
                                     self_field,
                                     substructure.method_ident,
diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs
index 15fb6ee9ff7..be13e103a72 100644
--- a/src/libsyntax/ext/deriving/iter_bytes.rs
+++ b/src/libsyntax/ext/deriving/iter_bytes.rs
@@ -56,8 +56,9 @@ fn iter_bytes_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @
     let iter_bytes_ident = substr.method_ident;
     let call_iterbytes = |thing_expr| {
         cx.expr_method_call(span,
-                              thing_expr, iter_bytes_ident,
-                              ~[lsb0, borrowed_f])
+                            thing_expr,
+                            iter_bytes_ident,
+                            ~[lsb0, borrowed_f])
     };
     let mut exprs = ~[];
     let fields;
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index cc2050d9bd7..823f21401ca 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -61,7 +61,7 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
     ];
     let rand_call = || {
         cx.expr_call_global(span,
-                            copy rand_ident,
+                            rand_ident.clone(),
                             ~[ rng[0].duplicate(cx) ])
     };
 
@@ -79,7 +79,11 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
             // need to specify the uint-ness of the random number
             let uint_ty = cx.ty_ident(span, cx.ident_of("uint"));
             let r_ty = cx.ty_ident(span, cx.ident_of("R"));
-            let rand_name = cx.path_all(span, true, copy rand_ident, None, ~[ uint_ty, r_ty ]);
+            let rand_name = cx.path_all(span,
+                                        true,
+                                        rand_ident.clone(),
+                                        None,
+                                        ~[ uint_ty, r_ty ]);
             let rand_name = cx.expr_path(rand_name);
 
             // ::std::rand::Rand::rand::<uint>(rng)
diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs
index 471e7212352..5bee804d582 100644
--- a/src/libsyntax/ext/deriving/zero.rs
+++ b/src/libsyntax/ext/deriving/zero.rs
@@ -63,7 +63,7 @@ fn zero_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
         cx.ident_of("zero")
     ];
     let zero_call = || {
-        cx.expr_call_global(span, copy zero_ident, ~[])
+        cx.expr_call_global(span, zero_ident.clone(), ~[])
     };
 
     return match *substr.fields {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 3f7579c7691..ba8e3e72933 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -83,7 +83,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
 
                             //keep going, outside-in
                             let fully_expanded =
-                                copy fld.fold_expr(expanded).node;
+                                fld.fold_expr(expanded).node.clone();
                             cx.bt_pop();
 
                             (fully_expanded, s)
@@ -208,7 +208,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
                     -> Option<@ast::item> {
     let (pth, tts) = match it.node {
         item_mac(codemap::spanned { node: mac_invoc_tt(ref pth, ref tts), _}) => {
-            (pth, copy *tts)
+            (pth, (*tts).clone())
         }
         _ => cx.span_bug(it.span, "invalid item macro invocation")
     };
@@ -298,7 +298,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
         stmt_mac(ref mac, semi) => {
             match mac.node {
                 mac_invoc_tt(ref pth, ref tts) => {
-                    (copy *mac, pth, copy *tts, semi)
+                    ((*mac).clone(), pth, (*tts).clone(), semi)
                 }
             }
         }
@@ -337,7 +337,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
                 Some(stmt) => {
                     let fully_expanded = &stmt.node;
                     cx.bt_pop();
-                    copy *fully_expanded
+                    (*fully_expanded).clone()
                 }
                 None => {
                     cx.span_fatal(pth.span,
@@ -725,7 +725,7 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess,
     // every method/element of AstFoldFns in fold.rs.
     let extsbox = @mut syntax_expander_table();
     let afp = default_ast_fold();
-    let cx = ExtCtxt::new(parse_sess, copy cfg);
+    let cx = ExtCtxt::new(parse_sess, cfg.clone());
     let f_pre = @AstFoldFns {
         fold_expr: |expr,span,recur|
             expand_expr(extsbox, cx, expr, span, recur, afp.fold_expr),
diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs
index a4873e6e34b..eb8b01c427d 100644
--- a/src/libsyntax/ext/pipes/ast_builder.rs
+++ b/src/libsyntax/ext/pipes/ast_builder.rs
@@ -49,15 +49,15 @@ pub trait append_types {
 impl append_types for ast::Path {
     fn add_ty(&self, ty: ast::Ty) -> ast::Path {
         ast::Path {
-            types: vec::append_one(copy self.types, ty),
-            .. copy *self
+            types: vec::append_one(self.types.clone(), ty),
+            .. (*self).clone()
         }
     }
 
     fn add_tys(&self, tys: ~[ast::Ty]) -> ast::Path {
         ast::Path {
-            types: vec::append(copy self.types, tys),
-            .. copy *self
+            types: vec::append(self.types.clone(), tys),
+            .. (*self).clone()
         }
     }
 }
diff --git a/src/libsyntax/ext/pipes/mod.rs b/src/libsyntax/ext/pipes/mod.rs
index 73c6c6d5fff..b8a0da8fe8f 100644
--- a/src/libsyntax/ext/pipes/mod.rs
+++ b/src/libsyntax/ext/pipes/mod.rs
@@ -67,7 +67,7 @@ pub fn expand_proto(cx: @ExtCtxt, _sp: span, id: ast::ident,
     let cfg = cx.cfg();
     let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic,
                                None,
-                               copy tt);
+                               tt.clone());
     let rdr = tt_rdr as @reader;
     let rust_parser = Parser(sess, cfg, rdr.dup());
 
diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs
index 21bb8266239..e5219721594 100644
--- a/src/libsyntax/ext/pipes/parse_proto.rs
+++ b/src/libsyntax/ext/pipes/parse_proto.rs
@@ -44,7 +44,7 @@ impl proto_parser for parser::Parser {
         let name = interner_get(id.name);
 
         self.expect(&token::COLON);
-        let dir = match copy *self.token {
+        let dir = match (*self.token).clone() {
             token::IDENT(n, _) => interner_get(n.name),
             _ => fail!()
         };
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index e5581cada37..b046c99d144 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -56,7 +56,8 @@ impl gen_send for message {
                 next.generics.ty_params.len());
             let arg_names = vec::from_fn(tys.len(), |i| cx.ident_of("x_"+i.to_str()));
             let args_ast: ~[ast::arg] = arg_names.iter().zip(tys.iter())
-                .transform(|(n, t)| cx.arg(span, copy *n, copy *t)).collect();
+                .transform(|(n, t)|
+                    cx.arg(span, (*n).clone(), (*t).clone())).collect();
 
             let pipe_ty = cx.ty_path(
                 path(~[this.data_name()], span)
@@ -117,7 +118,7 @@ impl gen_send for message {
 
             let mut rty = cx.ty_path(path(~[next.data_name()],
                                           span)
-                                     .add_tys(copy next_state.tys), None);
+                                     .add_tys(next_state.tys.clone()), None);
             if try {
                 rty = cx.ty_option(rty);
             }
@@ -137,7 +138,8 @@ impl gen_send for message {
                 let arg_names = vec::from_fn(tys.len(), |i| "x_" + i.to_str());
 
                 let args_ast: ~[ast::arg] = arg_names.iter().zip(tys.iter())
-                    .transform(|(n, t)| cx.arg(span, cx.ident_of(*n), copy *t)).collect();
+                    .transform(|(n, t)|
+                        cx.arg(span, cx.ident_of(*n), (*t).clone())).collect();
 
                 let args_ast = vec::append(
                     ~[cx.arg(span,
@@ -152,7 +154,7 @@ impl gen_send for message {
                     ~""
                 }
                 else {
-                    ~"(" + arg_names.map(|x| copy *x).connect(", ") + ")"
+                    ~"(" + arg_names.map(|x| (*x).clone()).connect(", ") + ")"
                 };
 
                 let mut body = ~"{ ";
@@ -209,7 +211,7 @@ impl to_type_decls for state {
         let mut items_msg = ~[];
 
         for self.messages.iter().advance |m| {
-            let message(name, span, tys, this, next) = copy *m;
+            let message(name, span, tys, this, next) = (*m).clone();
 
             let tys = match next {
               Some(ref next_state) => {
@@ -225,7 +227,7 @@ impl to_type_decls for state {
                                 cx.ty_path(
                                     path(~[cx.ident_of(dir),
                                            cx.ident_of(next_name)], span)
-                                    .add_tys(copy next_state.tys), None))
+                                    .add_tys(next_state.tys.clone()), None))
               }
               None => tys
             };
@@ -374,7 +376,7 @@ impl gen_init for protocol {
         for self.states.iter().advance |s| {
             for s.generics.ty_params.iter().advance |tp| {
                 match params.iter().find_(|tpp| tp.ident == tpp.ident) {
-                  None => params.push(copy *tp),
+                  None => params.push((*tp).clone()),
                   _ => ()
                 }
             }
@@ -392,7 +394,7 @@ impl gen_init for protocol {
         let fields = do self.states.iter().transform |s| {
             for s.generics.ty_params.iter().advance |tp| {
                 match params.iter().find_(|tpp| tp.ident == tpp.ident) {
-                  None => params.push(copy *tp),
+                  None => params.push((*tp).clone()),
                   _ => ()
                 }
             }
diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs
index 92e1b2bd09f..c93b89daa40 100644
--- a/src/libsyntax/ext/pipes/proto.rs
+++ b/src/libsyntax/ext/pipes/proto.rs
@@ -35,12 +35,14 @@ impl direction {
     }
 }
 
+#[deriving(Clone)]
 pub struct next_state {
     state: @str,
     tys: ~[ast::Ty],
 }
 
 // name, span, data, current state, next state
+#[deriving(Clone)]
 pub struct message(@str, span, ~[ast::Ty], state, Option<next_state>);
 
 impl message {
@@ -59,7 +61,7 @@ impl message {
     /// Return the type parameters actually used by this message
     pub fn get_generics(&self) -> ast::Generics {
         match *self {
-          message(_, _, _, this, _) => copy this.generics
+          message(_, _, _, this, _) => this.generics.clone()
         }
     }
 }
@@ -216,7 +218,7 @@ pub fn visit<Tproto, Tstate, Tmessage, V: visitor<Tproto, Tstate, Tmessage>>(
 
     let states: ~[Tstate] = do proto.states.iter().transform |&s| {
         let messages: ~[Tmessage] = do s.messages.iter().transform |m| {
-            let message(name, span, tys, this, next) = copy *m;
+            let message(name, span, tys, this, next) = (*m).clone();
             visitor.visit_message(name, span, tys, this, next)
         }.collect();
         visitor.visit_state(s, messages)
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 3e0e9c93fd0..80e3953da86 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -45,7 +45,7 @@ pub mod rt {
 
     impl ToTokens for ~[token_tree] {
         pub fn to_tokens(&self, _cx: @ExtCtxt) -> ~[token_tree] {
-            copy *self
+            (*self).clone()
         }
     }
 
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index b43536389e2..626a562b92c 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -148,6 +148,6 @@ fn res_rel_file(cx: @ExtCtxt, sp: codemap::span, arg: &Path) -> Path {
         let cu = Path(cx.codemap().span_to_filename(sp));
         cu.dir_path().push_many(arg.components)
     } else {
-        copy *arg
+        (*arg).clone()
     }
 }
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index 5c6032785e3..f7f17d3ba64 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -26,11 +26,7 @@ pub fn expand_trace_macros(cx: @ExtCtxt,
                                None,
                                tt.to_owned());
     let rdr = tt_rdr as @reader;
-    let rust_parser = Parser(
-        sess,
-        copy cfg,
-        rdr.dup()
-    );
+    let rust_parser = Parser(sess, cfg.clone(), rdr.dup());
 
     if rust_parser.is_keyword(keywords::True) {
         cx.set_trace_macros(true);
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index cddba358373..54ccd489171 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -96,6 +96,7 @@ eof: [a $( a )* a b ·]
 /* to avoid costly uniqueness checks, we require that `match_seq` always has a
 nonempty body. */
 
+#[deriving(Clone)]
 pub enum matcher_pos_up { /* to break a circularity */
     matcher_pos_up(Option<~MatcherPos>)
 }
@@ -107,6 +108,7 @@ pub fn is_some(mpu: &matcher_pos_up) -> bool {
     }
 }
 
+#[deriving(Clone)]
 pub struct MatcherPos {
     elts: ~[ast::matcher], // maybe should be <'>? Need to understand regions.
     sep: Option<Token>,
@@ -119,7 +121,7 @@ pub struct MatcherPos {
 
 pub fn copy_up(mpu: &matcher_pos_up) -> ~MatcherPos {
     match *mpu {
-      matcher_pos_up(Some(ref mp)) => copy (*mp),
+      matcher_pos_up(Some(ref mp)) => (*mp).clone(),
       _ => fail!()
     }
 }
@@ -279,7 +281,7 @@ pub fn parse(
 
                         // Only touch the binders we have actually bound
                         for uint::range(ei.match_lo, ei.match_hi) |idx| {
-                            let sub = copy ei.matches[idx];
+                            let sub = ei.matches[idx].clone();
                             new_pos.matches[idx]
                                 .push(@matched_seq(sub,
                                                    mk_sp(ei.sp_lo,
@@ -293,10 +295,10 @@ pub fn parse(
                     // can we go around again?
 
                     // the *_t vars are workarounds for the lack of unary move
-                    match copy ei.sep {
+                    match ei.sep {
                       Some(ref t) if idx == len => { // we need a separator
                         if tok == (*t) { //pass the separator
-                            let mut ei_t = ei;
+                            let mut ei_t = ei.clone();
                             ei_t.idx += 1;
                             next_eis.push(ei_t);
                         }
@@ -311,12 +313,12 @@ pub fn parse(
                     eof_eis.push(ei);
                 }
             } else {
-                match copy ei.elts[idx].node {
+                match ei.elts[idx].node.clone() {
                   /* need to descend into sequence */
                   match_seq(ref matchers, ref sep, zero_ok,
                             match_idx_lo, match_idx_hi) => {
                     if zero_ok {
-                        let mut new_ei = copy ei;
+                        let mut new_ei = ei.clone();
                         new_ei.idx += 1u;
                         //we specifically matched zero repeats.
                         for uint::range(match_idx_lo, match_idx_hi) |idx| {
@@ -329,8 +331,8 @@ pub fn parse(
                     let matches = vec::from_elem(ei.matches.len(), ~[]);
                     let ei_t = ei;
                     cur_eis.push(~MatcherPos {
-                        elts: copy *matchers,
-                        sep: copy *sep,
+                        elts: (*matchers).clone(),
+                        sep: (*sep).clone(),
                         idx: 0u,
                         up: matcher_pos_up(Some(ei_t)),
                         matches: matches,
@@ -340,7 +342,7 @@ pub fn parse(
                   }
                   match_nonterminal(_,_,_) => { bb_eis.push(ei) }
                   match_tok(ref t) => {
-                    let mut ei_t = ei;
+                    let mut ei_t = ei.clone();
                     if (*t) == tok {
                         ei_t.idx += 1;
                         next_eis.push(ei_t);
@@ -388,7 +390,7 @@ pub fn parse(
                 }
                 rdr.next_token();
             } else /* bb_eis.len() == 1 */ {
-                let rust_parser = Parser(sess, copy cfg, rdr.dup());
+                let rust_parser = Parser(sess, cfg.clone(), rdr.dup());
 
                 let mut ei = bb_eis.pop();
                 match ei.elts[ei.idx].node {
@@ -426,7 +428,7 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal {
       "ident" => match *p.token {
         token::IDENT(sn,b) => { p.bump(); token::nt_ident(sn,b) }
         _ => p.fatal(~"expected ident, found "
-                     + token::to_str(get_ident_interner(), &copy *p.token))
+                     + token::to_str(get_ident_interner(), p.token))
       },
       "path" => token::nt_path(p.parse_path_with_tps(false)),
       "tt" => {
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 6b3ce1c9a2f..399a1827c68 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -32,7 +32,10 @@ pub fn add_new_extension(cx: @ExtCtxt,
                       -> base::MacResult {
     // these spans won't matter, anyways
     fn ms(m: matcher_) -> matcher {
-        spanned { node: copy m, span: dummy_sp() }
+        spanned {
+            node: m.clone(),
+            span: dummy_sp()
+        }
     }
 
     let lhs_nm =  gensym_ident("lhs");
@@ -55,7 +58,7 @@ pub fn add_new_extension(cx: @ExtCtxt,
     // Parse the macro_rules! invocation (`none` is for no interpolations):
     let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic,
                                    None,
-                                   copy arg);
+                                   arg.clone());
     let argument_map = parse_or_else(cx.parse_sess(),
                                      cx.cfg(),
                                      arg_reader as @reader,
@@ -63,12 +66,12 @@ pub fn add_new_extension(cx: @ExtCtxt,
 
     // Extract the arguments:
     let lhses = match *argument_map.get(&lhs_nm) {
-        @matched_seq(ref s, _) => /* FIXME (#2543) */ @copy *s,
+        @matched_seq(ref s, _) => /* FIXME (#2543) */ @(*s).clone(),
         _ => cx.span_bug(sp, "wrong-structured lhs")
     };
 
     let rhses = match *argument_map.get(&rhs_nm) {
-      @matched_seq(ref s, _) => /* FIXME (#2543) */ @copy *s,
+      @matched_seq(ref s, _) => /* FIXME (#2543) */ @(*s).clone(),
       _ => cx.span_bug(sp, "wrong-structured rhs")
     };
 
@@ -132,7 +135,7 @@ pub fn add_new_extension(cx: @ExtCtxt,
                   }
                   failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                     best_fail_spot = sp;
-                    best_fail_msg = copy *msg;
+                    best_fail_msg = (*msg).clone();
                   },
                   error(sp, ref msg) => cx.span_fatal(sp, (*msg))
                 }
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 94ecff178ea..67318c60db9 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -74,10 +74,10 @@ pub fn new_tt_reader(sp_diag: @span_handler,
 
 fn dup_tt_frame(f: @mut TtFrame) -> @mut TtFrame {
     @mut TtFrame {
-        forest: @mut (copy *f.forest),
+        forest: @mut (*f.forest).clone(),
         idx: f.idx,
         dotdotdoted: f.dotdotdoted,
-        sep: copy f.sep,
+        sep: f.sep.clone(),
         up: match f.up {
             Some(up_frame) => Some(dup_tt_frame(up_frame)),
             None => None
@@ -89,11 +89,11 @@ pub fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader {
     @mut TtReader {
         sp_diag: r.sp_diag,
         stack: dup_tt_frame(r.stack),
-        repeat_idx: copy r.repeat_idx,
-        repeat_len: copy r.repeat_len,
-        cur_tok: copy r.cur_tok,
+        repeat_idx: r.repeat_idx.clone(),
+        repeat_len: r.repeat_len.clone(),
+        cur_tok: r.cur_tok.clone(),
         cur_span: r.cur_span,
-        interpolations: copy r.interpolations,
+        interpolations: r.interpolations.clone(),
     }
 }
 
@@ -122,19 +122,23 @@ fn lookup_cur_matched(r: &mut TtReader, name: ident) -> @named_match {
         }
     }
 }
+
+#[deriving(Clone)]
 enum lis {
-    lis_unconstrained, lis_constraint(uint, ident), lis_contradiction(~str)
+    lis_unconstrained,
+    lis_constraint(uint, ident),
+    lis_contradiction(~str),
 }
 
 fn lockstep_iter_size(t: &token_tree, r: &mut TtReader) -> lis {
     fn lis_merge(lhs: lis, rhs: lis) -> lis {
         match lhs {
-          lis_unconstrained => copy rhs,
-          lis_contradiction(_) => copy lhs,
+          lis_unconstrained => rhs.clone(),
+          lis_contradiction(_) => lhs.clone(),
           lis_constraint(l_len, ref l_id) => match rhs {
-            lis_unconstrained => copy lhs,
-            lis_contradiction(_) => copy rhs,
-            lis_constraint(r_len, _) if l_len == r_len => copy lhs,
+            lis_unconstrained => lhs.clone(),
+            lis_contradiction(_) => rhs.clone(),
+            lis_constraint(r_len, _) if l_len == r_len => lhs.clone(),
             lis_constraint(r_len, ref r_id) => {
                 let l_n = ident_to_str(l_id);
                 let r_n = ident_to_str(r_id);
@@ -163,8 +167,9 @@ fn lockstep_iter_size(t: &token_tree, r: &mut TtReader) -> lis {
 // return the next token from the TtReader.
 // EFFECT: advances the reader's token field
 pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
+    // XXX(pcwalton): Bad copy?
     let ret_val = TokenAndSpan {
-        tok: copy r.cur_tok,
+        tok: r.cur_tok.clone(),
         sp: r.cur_span,
     };
     loop {
@@ -199,7 +204,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
         } else { /* repeat */
             r.stack.idx = 0u;
             r.repeat_idx[r.repeat_idx.len() - 1u] += 1u;
-            match copy r.stack.sep {
+            match r.stack.sep.clone() {
               Some(tk) => {
                 r.cur_tok = tk; /* repeat same span, I guess */
                 return ret_val;
@@ -210,7 +215,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
     }
     loop { /* because it's easiest, this handles `tt_delim` not starting
     with a `tt_tok`, even though it won't happen */
-        match copy r.stack.forest[r.stack.idx] {
+        // XXX(pcwalton): Bad copy.
+        match r.stack.forest[r.stack.idx].clone() {
           tt_delim(tts) => {
             r.stack = @mut TtFrame {
                 forest: @mut tts,
@@ -228,7 +234,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
             return ret_val;
           }
           tt_seq(sp, tts, sep, zerok) => {
-            let t = tt_seq(sp, copy tts, copy sep, zerok);
+            // XXX(pcwalton): Bad copy.
+            let t = tt_seq(sp, tts.clone(), sep.clone(), zerok);
             match lockstep_iter_size(&t, r) {
               lis_unconstrained => {
                 r.sp_diag.span_fatal(
@@ -278,8 +285,9 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
                 return ret_val;
               }
               matched_nonterminal(ref other_whole_nt) => {
+                // XXX(pcwalton): Bad copy.
                 r.cur_span = sp;
-                r.cur_tok = INTERPOLATED(copy *other_whole_nt);
+                r.cur_tok = INTERPOLATED((*other_whole_nt).clone());
                 r.stack.idx += 1u;
                 return ret_val;
               }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 11c29c73a2b..b831bb18643 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -144,17 +144,17 @@ fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] {
 }
 
 // apply ident folder if it's an ident, otherwise leave it alone
-fn maybe_fold_ident(t : &token::Token, fld: @ast_fold) -> token::Token {
+fn maybe_fold_ident(t: &token::Token, fld: @ast_fold) -> token::Token {
     match *t {
         token::IDENT(id,followed_by_colons) =>
         token::IDENT(fld.fold_ident(id),followed_by_colons),
-        _ => copy *t
+        _ => (*t).clone()
     }
 }
 
 pub fn fold_fn_decl(decl: &ast::fn_decl, fld: @ast_fold) -> ast::fn_decl {
     ast::fn_decl {
-        inputs: decl.inputs.map(|x| fold_arg_(/*bad*/ copy *x, fld)),
+        inputs: decl.inputs.map(|x| fold_arg_(/*bad*/ (*x).clone(), fld)),
         output: fld.fold_ty(&decl.output),
         cf: decl.cf,
     }
@@ -176,7 +176,7 @@ pub fn fold_ty_param(tp: TyParam,
 
 pub fn fold_ty_params(tps: &OptVec<TyParam>,
                       fld: @ast_fold) -> OptVec<TyParam> {
-    let tps = /*bad*/ copy *tps;
+    let tps = /*bad*/ (*tps).clone();
     tps.map_consume(|tp| fold_ty_param(tp, fld))
 }
 
@@ -209,7 +209,7 @@ pub fn noop_fold_crate(c: &crate_, fld: @ast_fold) -> crate_ {
 }
 
 fn noop_fold_view_item(vi: &view_item_, _fld: @ast_fold) -> view_item_ {
-    return /* FIXME (#2543) */ copy *vi;
+    return /* FIXME (#2543) */ (*vi).clone();
 }
 
 
@@ -226,7 +226,8 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold)
                 foreign_item_fn(ref fdec, purity, ref generics) => {
                     foreign_item_fn(
                         ast::fn_decl {
-                            inputs: fdec.inputs.map(|a| fold_arg(/*bad*/copy *a)),
+                            inputs: fdec.inputs.map(|a|
+                                fold_arg(/*bad*/(*a).clone())),
                             output: fld.fold_ty(&fdec.output),
                             cf: fdec.cf,
                         },
@@ -299,7 +300,7 @@ pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
         }
         item_struct(ref struct_def, ref generics) => {
             let struct_def = fold_struct_def(*struct_def, fld);
-            item_struct(struct_def, /* FIXME (#2543) */ copy *generics)
+            item_struct(struct_def, /* FIXME (#2543) */ (*generics).clone())
         }
         item_impl(ref generics, ref ifce, ref ty, ref methods) => {
             item_impl(
@@ -312,7 +313,7 @@ pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
         item_trait(ref generics, ref traits, ref methods) => {
             let methods = do methods.map |method| {
                 match *method {
-                    required(*) => copy *method,
+                    required(*) => (*method).clone(),
                     provided(method) => provided(fld.fold_method(method))
                 }
             };
@@ -353,7 +354,7 @@ fn fold_struct_field(f: @struct_field, fld: @ast_fold) -> @struct_field {
             kind: f.node.kind,
             id: fld.new_id(f.node.id),
             ty: fld.fold_ty(&f.node.ty),
-            attrs: /* FIXME (#2543) */ copy f.node.attrs,
+            attrs: /* FIXME (#2543) */ f.node.attrs.clone(),
         },
         span: fld.new_span(f.span),
     }
@@ -362,7 +363,7 @@ fn fold_struct_field(f: @struct_field, fld: @ast_fold) -> @struct_field {
 fn noop_fold_method(m: @method, fld: @ast_fold) -> @method {
     @ast::method {
         ident: fld.fold_ident(m.ident),
-        attrs: /* FIXME (#2543) */ copy m.attrs,
+        attrs: /* FIXME (#2543) */ m.attrs.clone(),
         generics: fold_generics(&m.generics, fld),
         explicit_self: m.explicit_self,
         purity: m.purity,
@@ -545,8 +546,10 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
         }
         expr_loop_body(f) => expr_loop_body(fld.fold_expr(f)),
         expr_do_body(f) => expr_do_body(fld.fold_expr(f)),
-        expr_lit(_) => copy *e,
-        expr_cast(expr, ref ty) => expr_cast(fld.fold_expr(expr), copy *ty),
+        expr_lit(_) => (*e).clone(),
+        expr_cast(expr, ref ty) => {
+            expr_cast(fld.fold_expr(expr), (*ty).clone())
+        }
         expr_addr_of(m, ohs) => expr_addr_of(m, fld.fold_expr(ohs)),
         expr_if(cond, ref tr, fl) => {
             expr_if(
@@ -623,7 +626,7 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
             expr_inline_asm(inline_asm {
                 inputs: a.inputs.map(|&(c, in)| (c, fld.fold_expr(in))),
                 outputs: a.outputs.map(|&(c, out)| (c, fld.fold_expr(out))),
-                .. copy *a
+                .. (*a).clone()
             })
         }
         expr_mac(ref mac) => expr_mac(fold_mac(mac)),
@@ -662,7 +665,7 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
         }
     }
     match *t {
-        ty_nil | ty_bot | ty_infer => copy *t,
+        ty_nil | ty_bot | ty_infer => (*t).clone(),
         ty_box(ref mt) => ty_box(fold_mt(mt, fld)),
         ty_uniq(ref mt) => ty_uniq(fold_mt(mt, fld)),
         ty_vec(ref mt) => ty_vec(fold_mt(mt, fld)),
@@ -676,12 +679,12 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
                 onceness: f.onceness,
                 bounds: fold_opt_bounds(&f.bounds, fld),
                 decl: fold_fn_decl(&f.decl, fld),
-                lifetimes: copy f.lifetimes,
+                lifetimes: f.lifetimes.clone(),
             })
         }
         ty_bare_fn(ref f) => {
             ty_bare_fn(@TyBareFn {
-                lifetimes: copy f.lifetimes,
+                lifetimes: f.lifetimes.clone(),
                 purity: f.purity,
                 abis: f.abis,
                 decl: fold_fn_decl(&f.decl, fld)
@@ -727,7 +730,7 @@ fn noop_fold_variant(v: &variant_, fld: @ast_fold) -> variant_ {
     match v.kind {
         tuple_variant_kind(ref variant_args) => {
             kind = tuple_variant_kind(do variant_args.map |x| {
-                fold_variant_arg(/*bad*/ copy *x)
+                fold_variant_arg(/*bad*/ (*x).clone())
             })
         }
         struct_variant_kind(struct_def) => {
@@ -844,7 +847,7 @@ impl ast_fold for AstFoldFns {
                 kind: sf.node.kind,
                 id: sf.node.id,
                 ty: self.fold_ty(&sf.node.ty),
-                attrs: copy sf.node.attrs,
+                attrs: sf.node.attrs.clone(),
             },
             span: (self.new_span)(sf.span),
         }
diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs
index ba3b72ec194..6ec80140c76 100644
--- a/src/libsyntax/opt_vec.rs
+++ b/src/libsyntax/opt_vec.rs
@@ -18,7 +18,7 @@
 
 use std::vec::{VecIterator};
 
-#[deriving(Encodable, Decodable,IterBytes)]
+#[deriving(Clone, Encodable, Decodable, IterBytes)]
 pub enum OptVec<T> {
     Empty,
     Vec(~[T])
@@ -113,7 +113,7 @@ pub fn take_vec<T>(v: OptVec<T>) -> ~[T] {
     }
 }
 
-impl<T:Copy> OptVec<T> {
+impl<T:Clone> OptVec<T> {
     fn prepend(&self, t: T) -> OptVec<T> {
         let mut v0 = ~[t];
         match *self {
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index d33b72ae3c9..85c7d5de064 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -39,7 +39,7 @@ impl parser_attr for Parser {
         loop {
             match *self.token {
               token::POUND => {
-                if self.look_ahead(1u) != token::LBRACKET {
+                if self.look_ahead(1, |t| *t != token::LBRACKET) {
                     break;
                 }
                 attrs.push(self.parse_attribute(ast::attr_outer));
@@ -96,7 +96,7 @@ impl parser_attr for Parser {
         loop {
             match *self.token {
               token::POUND => {
-                if self.look_ahead(1u) != token::LBRACKET {
+                if self.look_ahead(1, |t| *t != token::LBRACKET) {
                     // This is an extension
                     break;
                 }
@@ -162,12 +162,10 @@ impl parser_attr for Parser {
 
     // matches meta_seq = ( COMMASEP(meta_item) )
     fn parse_meta_seq(&self) -> ~[@ast::meta_item] {
-        copy self.parse_seq(
-            &token::LPAREN,
-            &token::RPAREN,
-            seq_sep_trailing_disallowed(token::COMMA),
-            |p| p.parse_meta_item()
-        ).node
+        self.parse_seq(&token::LPAREN,
+                       &token::RPAREN,
+                       seq_sep_trailing_disallowed(token::COMMA),
+                       |p| p.parse_meta_item()).node
     }
 
     fn parse_optional_meta(&self) -> ~[@ast::meta_item] {
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index 01af33b13b8..83af5bade3a 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -22,7 +22,7 @@ use std::io;
 use std::str;
 use std::uint;
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub enum cmnt_style {
     isolated, // No code on either side of each line of the comment
     trailing, // Code exists to the left of the comment
@@ -30,6 +30,7 @@ pub enum cmnt_style {
     blank_line, // Just a manual blank line "\n\n", for layout
 }
 
+#[deriving(Clone)]
 pub struct cmnt {
     style: cmnt_style,
     lines: ~[~str],
@@ -324,6 +325,7 @@ fn consume_comment(rdr: @mut StringReader,
     debug!("<<< consume comment");
 }
 
+#[deriving(Clone)]
 pub struct lit {
     lit: ~str,
     pos: BytePos
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 22e0a150a19..8db80cddded 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -20,6 +20,7 @@ use parse::token::{str_to_ident};
 use std::char;
 use std::either;
 use std::u64;
+use std::util;
 
 pub use ext::tt::transcribe::{TtReader, new_tt_reader};
 
@@ -93,7 +94,7 @@ fn dup_string_reader(r: @mut StringReader) -> @mut StringReader {
         col: r.col,
         curr: r.curr,
         filemap: r.filemap,
-        peek_tok: copy r.peek_tok,
+        peek_tok: r.peek_tok.clone(),
         peek_span: r.peek_span
     }
 }
@@ -103,7 +104,7 @@ impl reader for StringReader {
     // return the next token. EFFECT: advances the string_reader.
     fn next_token(@mut self) -> TokenAndSpan {
         let ret_val = TokenAndSpan {
-            tok: /*bad*/copy self.peek_tok,
+            tok: util::replace(&mut self.peek_tok, token::UNDERSCORE),
             sp: self.peek_span,
         };
         string_advance_token(self);
@@ -114,8 +115,9 @@ impl reader for StringReader {
     }
     fn span_diag(@mut self) -> @span_handler { self.span_diagnostic }
     fn peek(@mut self) -> TokenAndSpan {
+        // XXX(pcwalton): Bad copy!
         TokenAndSpan {
-            tok: /*bad*/copy self.peek_tok,
+            tok: self.peek_tok.clone(),
             sp: self.peek_span,
         }
     }
@@ -131,7 +133,7 @@ impl reader for TtReader {
     fn span_diag(@mut self) -> @span_handler { self.sp_diag }
     fn peek(@mut self) -> TokenAndSpan {
         TokenAndSpan {
-            tok: copy self.cur_tok,
+            tok: self.cur_tok.clone(),
             sp: self.cur_span,
         }
     }
@@ -143,8 +145,8 @@ impl reader for TtReader {
 fn string_advance_token(r: @mut StringReader) {
     match (consume_whitespace_and_comments(r)) {
         Some(comment) => {
-            r.peek_tok = copy comment.tok;
             r.peek_span = comment.sp;
+            r.peek_tok = comment.tok;
         },
         None => {
             if is_eof(r) {
@@ -818,7 +820,7 @@ mod test {
             sp:span {lo:BytePos(21),hi:BytePos(23),expn_info: None}};
         assert_eq!(tok1,tok2);
         // the 'main' id is already read:
-        assert_eq!(copy string_reader.last_pos,BytePos(28));
+        assert_eq!(string_reader.last_pos.clone(), BytePos(28));
         // read another token:
         let tok3 = string_reader.next_token();
         let tok4 = TokenAndSpan{
@@ -826,7 +828,7 @@ mod test {
             sp:span {lo:BytePos(24),hi:BytePos(28),expn_info: None}};
         assert_eq!(tok3,tok4);
         // the lparen is already read:
-        assert_eq!(copy string_reader.last_pos,BytePos(29))
+        assert_eq!(string_reader.last_pos.clone(), BytePos(29))
     }
 
     // check that the given reader produces the desired stream
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 84cc49192ed..410849b4482 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -79,7 +79,7 @@ pub fn parse_crate_from_file(
     cfg: ast::crate_cfg,
     sess: @mut ParseSess
 ) -> @ast::crate {
-    new_parser_from_file(sess, /*bad*/ copy cfg, input).parse_crate_mod()
+    new_parser_from_file(sess, /*bad*/ cfg.clone(), input).parse_crate_mod()
     // why is there no p.abort_if_errors here?
 }
 
@@ -89,12 +89,10 @@ pub fn parse_crate_from_source_str(
     cfg: ast::crate_cfg,
     sess: @mut ParseSess
 ) -> @ast::crate {
-    let p = new_parser_from_source_str(
-        sess,
-        /*bad*/ copy cfg,
-        name,
-        source
-    );
+    let p = new_parser_from_source_str(sess,
+                                       /*bad*/ cfg.clone(),
+                                       name,
+                                       source);
     maybe_aborted(p.parse_crate_mod(),p)
 }
 
@@ -457,7 +455,7 @@ mod test {
     }
 
     fn parser_done(p: Parser){
-        assert_eq!(copy *p.token,token::EOF);
+        assert_eq!((*p.token).clone(), token::EOF);
     }
 
     #[test] fn parse_ident_pat () {
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index 01ed6531273..148fca36ed2 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -314,8 +314,8 @@ impl ParserObsoleteMethods for Parser {
 
     pub fn try_parse_obsolete_with(&self) -> bool {
         if *self.token == token::COMMA
-            && self.token_is_obsolete_ident("with",
-                                            &self.look_ahead(1u)) {
+            && self.look_ahead(1,
+                               |t| self.token_is_obsolete_ident("with", t)) {
             self.bump();
         }
         if self.eat_obsolete_ident("with") {
@@ -329,8 +329,8 @@ impl ParserObsoleteMethods for Parser {
 
     pub fn try_parse_obsolete_priv_section(&self, attrs: &[attribute])
                                            -> bool {
-        if self.is_keyword(keywords::Priv) && self.look_ahead(1) ==
-                token::LBRACE {
+        if self.is_keyword(keywords::Priv) &&
+                self.look_ahead(1, |t| *t == token::LBRACE) {
             self.obsolete(*self.span, ObsoletePrivSection);
             self.eat_keyword(keywords::Priv);
             self.bump();
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 497000a6cbf..c67b2aefb63 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -97,6 +97,7 @@ use opt_vec::OptVec;
 use std::either::Either;
 use std::either;
 use std::hashmap::HashSet;
+use std::util;
 use std::vec;
 
 #[deriving(Eq)]
@@ -111,8 +112,9 @@ type arg_or_capture_item = Either<arg, ()>;
 type item_info = (ident, item_, Option<~[attribute]>);
 
 pub enum item_or_view_item {
-    // indicates a failure to parse any kind of item:
-    iovi_none,
+    // Indicates a failure to parse any kind of item. The attributes are
+    // returned.
+    iovi_none(~[attribute]),
     iovi_item(@item),
     iovi_foreign_item(@foreign_item),
     iovi_view_item(view_item)
@@ -141,7 +143,7 @@ macro_rules! maybe_whole_expr (
                     Some($p.mk_expr(
                         ($p).span.lo,
                         ($p).span.hi,
-                        expr_path(/* bad */ copy *pt)))
+                        expr_path(/* bad */ (*pt).clone())))
                 }
                 _ => None
             };
@@ -158,48 +160,83 @@ macro_rules! maybe_whole_expr (
 
 macro_rules! maybe_whole (
     ($p:expr, $constructor:ident) => (
-        match copy *($p).token {
-            INTERPOLATED(token::$constructor(x)) => {
-                $p.bump();
-                return x;
+        {
+            let __found__ = match *($p).token {
+                INTERPOLATED(token::$constructor(_)) => {
+                    Some(($p).bump_and_get())
+                }
+                _ => None
+            };
+            match __found__ {
+                Some(INTERPOLATED(token::$constructor(x))) => {
+                    return x.clone()
+                }
+                _ => {}
             }
-            _ => ()
-       }
+        }
     );
     (deref $p:expr, $constructor:ident) => (
-        match copy *($p).token {
-            INTERPOLATED(token::$constructor(x)) => {
-                $p.bump();
-                return copy *x;
+        {
+            let __found__ = match *($p).token {
+                INTERPOLATED(token::$constructor(_)) => {
+                    Some(($p).bump_and_get())
+                }
+                _ => None
+            };
+            match __found__ {
+                Some(INTERPOLATED(token::$constructor(x))) => {
+                    return (*x).clone()
+                }
+                _ => {}
             }
-            _ => ()
         }
     );
     (Some $p:expr, $constructor:ident) => (
-        match copy *($p).token {
-            INTERPOLATED(token::$constructor(x)) => {
-                $p.bump();
-                return Some(x);
+        {
+            let __found__ = match *($p).token {
+                INTERPOLATED(token::$constructor(_)) => {
+                    Some(($p).bump_and_get())
+                }
+                _ => None
+            };
+            match __found__ {
+                Some(INTERPOLATED(token::$constructor(x))) => {
+                    return Some(x.clone()),
+                }
+                _ => {}
             }
-            _ => ()
         }
     );
     (iovi $p:expr, $constructor:ident) => (
-        match copy *($p).token {
-            INTERPOLATED(token::$constructor(x)) => {
-                $p.bump();
-                return iovi_item(x);
+        {
+            let __found__ = match *($p).token {
+                INTERPOLATED(token::$constructor(_)) => {
+                    Some(($p).bump_and_get())
+                }
+                _ => None
+            };
+            match __found__ {
+                Some(INTERPOLATED(token::$constructor(x))) => {
+                    return iovi_item(x.clone())
+                }
+                _ => {}
             }
-            _ => ()
         }
     );
     (pair_empty $p:expr, $constructor:ident) => (
-        match copy *($p).token {
-            INTERPOLATED(token::$constructor(x)) => {
-                $p.bump();
-                return (~[], x);
+        {
+            let __found__ = match *($p).token {
+                INTERPOLATED(token::$constructor(_)) => {
+                    Some(($p).bump_and_get())
+                }
+                _ => None
+            };
+            match __found__ {
+                Some(INTERPOLATED(token::$constructor(x))) => {
+                    return (~[], x.clone())
+                }
+                _ => {}
             }
-            _ => ()
         }
     )
 )
@@ -227,18 +264,23 @@ pub fn Parser(sess: @mut ParseSess,
               cfg: ast::crate_cfg,
               rdr: @reader)
            -> Parser {
-    let tok0 = copy rdr.next_token();
+    let tok0 = rdr.next_token();
     let interner = get_ident_interner();
+    let span = tok0.sp;
+    let placeholder = TokenAndSpan {
+        tok: token::UNDERSCORE,
+        sp: span,
+    };
 
     Parser {
         reader: rdr,
         interner: interner,
         sess: sess,
         cfg: cfg,
-        token: @mut copy tok0.tok,
-        span: @mut tok0.sp,
-        last_span: @mut tok0.sp,
-        buffer: @mut ([copy tok0, .. 4]),
+        token: @mut tok0.tok,
+        span: @mut span,
+        last_span: @mut span,
+        buffer: @mut ([placeholder, .. 4]),
         buffer_start: @mut 0,
         buffer_end: @mut 0,
         tokens_consumed: @mut 0,
@@ -534,14 +576,29 @@ impl Parser {
         let next = if *self.buffer_start == *self.buffer_end {
             self.reader.next_token()
         } else {
-            let next = copy self.buffer[*self.buffer_start];
-            *self.buffer_start = (*self.buffer_start + 1) & 3;
-            next
+            // Avoid token copies with `util::replace`.
+            let buffer_start = *self.buffer_start as uint;
+            let next_index = (buffer_start + 1) & 3 as uint;
+            *self.buffer_start = next_index as int;
+
+            let placeholder = TokenAndSpan {
+                tok: token::UNDERSCORE,
+                sp: *self.span,
+            };
+            util::replace(&mut self.buffer[buffer_start], placeholder)
         };
-        *self.token = /*bad*/copy next.tok;
         *self.span = next.sp;
+        *self.token = next.tok;
         *self.tokens_consumed += 1u;
     }
+
+    // Advance the parser by one token and return the bumped token.
+    pub fn bump_and_get(&self) -> token::Token {
+        let old_token = util::replace(self.token, token::UNDERSCORE);
+        self.bump();
+        old_token
+    }
+
     // EFFECT: replace the current token and span with the given one
     pub fn replace_token(&self,
                          next: token::Token,
@@ -556,13 +613,14 @@ impl Parser {
         }
         return (4 - *self.buffer_start) + *self.buffer_end;
     }
-    pub fn look_ahead(&self, distance: uint) -> token::Token {
+    pub fn look_ahead<R>(&self, distance: uint, f: &fn(&token::Token) -> R)
+                         -> R {
         let dist = distance as int;
         while self.buffer_length() < dist {
             self.buffer[*self.buffer_end] = self.reader.next_token();
             *self.buffer_end = (*self.buffer_end + 1) & 3;
         }
-        return copy self.buffer[(*self.buffer_start + dist - 1) & 3].tok;
+        f(&self.buffer[(*self.buffer_start + dist - 1) & 3].tok)
     }
     pub fn fatal(&self, m: &str) -> ! {
         self.sess.span_diagnostic.span_fatal(*self.span, m)
@@ -902,11 +960,13 @@ impl Parser {
                         one_tuple = true;
                     }
                 }
-                let t = if ts.len() == 1 && !one_tuple {
-                    copy ts[0].node
-                } else {
-                    ty_tup(ts)
-                };
+
+                if ts.len() == 1 && !one_tuple {
+                    self.expect(&token::RPAREN);
+                    return ts[0]
+                }
+
+                let t = ty_tup(ts);
                 self.expect(&token::RPAREN);
                 t
             }
@@ -958,7 +1018,7 @@ impl Parser {
         } else if self.eat_keyword(keywords::Extern) {
             // EXTERN FUNCTION
             self.parse_ty_bare_fn()
-        } else if self.token_is_closure_keyword(&copy *self.token) {
+        } else if self.token_is_closure_keyword(self.token) {
             // CLOSURE
             let result = self.parse_ty_closure(ast::BorrowedSigil, None);
             self.obsolete(*self.last_span, ObsoleteBareFnType);
@@ -990,13 +1050,13 @@ impl Parser {
             }
 
             token::IDENT(*) => {
-                if self.look_ahead(1u) == token::BINOP(token::SLASH) &&
-                    self.token_is_closure_keyword(&self.look_ahead(2u))
-                {
+                if self.look_ahead(1, |t| *t == token::BINOP(token::SLASH)) &&
+                        self.look_ahead(2, |t|
+                                        self.token_is_closure_keyword(t)) {
                     let lifetime = self.parse_lifetime();
                     self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
                     return self.parse_ty_closure(sigil, Some(lifetime));
-                } else if self.token_is_closure_keyword(&copy *self.token) {
+                } else if self.token_is_closure_keyword(self.token) {
                     return self.parse_ty_closure(sigil, None);
                 }
             }
@@ -1023,7 +1083,7 @@ impl Parser {
         // look for `&'lt` or `&'foo ` and interpret `foo` as the region name:
         let opt_lifetime = self.parse_opt_lifetime();
 
-        if self.token_is_closure_keyword(&copy *self.token) {
+        if self.token_is_closure_keyword(self.token) {
             return self.parse_ty_closure(BorrowedSigil, opt_lifetime);
         }
 
@@ -1056,7 +1116,7 @@ impl Parser {
         } else if *self.token == token::ANDAND {
             1
         } else if *self.token == token::BINOP(token::PLUS) {
-            if self.look_ahead(1) == token::BINOP(token::PLUS) {
+            if self.look_ahead(1, |t| *t == token::BINOP(token::PLUS)) {
                 2
             } else {
                 1
@@ -1064,10 +1124,10 @@ impl Parser {
         } else { 0 };
         if offset == 0 {
             is_plain_ident(&*self.token)
-                && self.look_ahead(1) == token::COLON
+                && self.look_ahead(1, |t| *t == token::COLON)
         } else {
-            is_plain_ident(&self.look_ahead(offset))
-                && self.look_ahead(offset + 1) == token::COLON
+            self.look_ahead(offset, |t| is_plain_ident(t))
+                && self.look_ahead(offset + 1, |t| *t == token::COLON)
         }
     }
 
@@ -1133,7 +1193,7 @@ impl Parser {
             self.obsolete(*self.last_span, ObsoleteFixedLengthVectorType);
             Some(self.parse_expr())
         } else if *self.token == token::COMMA &&
-                self.look_ahead(1) == token::DOTDOT {
+                self.look_ahead(1, |t| *t == token::DOTDOT) {
             self.bump();
             self.bump();
             Some(self.parse_expr())
@@ -1165,10 +1225,9 @@ impl Parser {
         } else if self.eat_keyword(keywords::False) {
             lit_bool(false)
         } else {
-            // XXX: This is a really bad copy!
-            let tok = copy *self.token;
-            self.bump();
-            self.lit_from_token(&tok)
+            let token = self.bump_and_get();
+            let lit = self.lit_from_token(&token);
+            lit
         };
         codemap::spanned { node: lit, span: mk_sp(lo, self.last_span.hi) }
     }
@@ -1209,12 +1268,17 @@ impl Parser {
         loop {
             match *self.token {
                 token::MOD_SEP => {
-                    match self.look_ahead(1) {
-                        token::IDENT(*) => {
-                            self.bump();
-                            ids.push(self.parse_ident());
+                    let is_ident = do self.look_ahead(1) |t| {
+                        match *t {
+                            token::IDENT(*) => true,
+                            _ => false,
                         }
-                        _ => break
+                    };
+                    if is_ident {
+                        self.bump();
+                        ids.push(self.parse_ident());
+                    } else {
+                        break
                     }
                 }
                 _ => break
@@ -1253,7 +1317,7 @@ impl Parser {
         // be written "foo/&x"
         let rp_slash = {
             if *self.token == token::BINOP(token::SLASH)
-                && self.look_ahead(1u) == token::BINOP(token::AND)
+                && self.look_ahead(1, |t| *t == token::BINOP(token::AND))
             {
                 self.bump(); self.bump();
                 self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
@@ -1294,10 +1358,12 @@ impl Parser {
             }
         };
 
-        ast::Path { span: mk_sp(lo, hi),
-                     rp: rp,
-                     types: tps,
-                     .. path }
+        ast::Path {
+            span: mk_sp(lo, hi),
+            rp: rp,
+            types: tps,
+            .. path.clone()
+        }
     }
 
     // parse a path optionally with type parameters. If 'colons'
@@ -1328,7 +1394,7 @@ impl Parser {
 
             // Also accept the (obsolete) syntax `foo/`
             token::IDENT(*) => {
-                if self.look_ahead(1u) == token::BINOP(token::SLASH) {
+                if self.look_ahead(1, |t| *t == token::BINOP(token::SLASH)) {
                     self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
                     Some(self.parse_lifetime())
                 } else {
@@ -1589,7 +1655,7 @@ impl Parser {
                 // Nonempty vector.
                 let first_expr = self.parse_expr();
                 if *self.token == token::COMMA &&
-                        self.look_ahead(1) == token::DOTDOT {
+                        self.look_ahead(1, |t| *t == token::DOTDOT) {
                     // Repeating vector syntax: [ 0, ..512 ]
                     self.bump();
                     self.bump();
@@ -1658,12 +1724,11 @@ impl Parser {
                 };
 
                 let ket = token::flip_delimiter(&*self.token);
-                let tts = self.parse_unspanned_seq(
-                    &copy *self.token,
-                    &ket,
-                    seq_sep_none(),
-                    |p| p.parse_token_tree()
-                );
+                self.bump();
+
+                let tts = self.parse_seq_to_end(&ket,
+                                                seq_sep_none(),
+                                                |p| p.parse_token_tree());
                 let hi = self.span.hi;
 
                 return self.mk_mac_expr(lo, hi, mac_invoc_tt(pth, tts));
@@ -1809,8 +1874,7 @@ impl Parser {
             self.bump();
             (None, zerok)
         } else {
-            let sep = copy *self.token;
-            self.bump();
+            let sep = self.bump_and_get();
             if *self.token == token::BINOP(token::STAR)
                 || *self.token == token::BINOP(token::PLUS) {
                 let zerok = *self.token == token::BINOP(token::STAR);
@@ -1877,9 +1941,7 @@ impl Parser {
 
         // turn the next token into a tt_tok:
         fn parse_any_tt_tok(p: &Parser) -> token_tree{
-            let res = tt_tok(*p.span, copy *p.token);
-            p.bump();
-            res
+            tt_tok(*p.span, p.bump_and_get())
         }
 
         match *self.token {
@@ -1925,32 +1987,25 @@ impl Parser {
         let name_idx = @mut 0u;
         match *self.token {
             token::LBRACE | token::LPAREN | token::LBRACKET => {
-                self.parse_matcher_subseq(
-                    name_idx,
-                    copy *self.token,
-                    // tjc: not sure why we need a copy
-                    token::flip_delimiter(self.token)
-                )
+                let other_delimiter = token::flip_delimiter(self.token);
+                self.bump();
+                self.parse_matcher_subseq_upto(name_idx, &other_delimiter)
             }
             _ => self.fatal("expected open delimiter")
         }
     }
 
-
     // This goofy function is necessary to correctly match parens in matchers.
     // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be
     // invalid. It's similar to common::parse_seq.
-    pub fn parse_matcher_subseq(&self,
-                                name_idx: @mut uint,
-                                bra: token::Token,
-                                ket: token::Token)
-                                -> ~[matcher] {
+    pub fn parse_matcher_subseq_upto(&self,
+                                     name_idx: @mut uint,
+                                     ket: &token::Token)
+                                     -> ~[matcher] {
         let mut ret_val = ~[];
         let mut lparens = 0u;
 
-        self.expect(&bra);
-
-        while *self.token != ket || lparens > 0u {
+        while *self.token != *ket || lparens > 0u {
             if *self.token == token::LPAREN { lparens += 1u; }
             if *self.token == token::RPAREN { lparens -= 1u; }
             ret_val.push(self.parse_matcher(name_idx));
@@ -1968,11 +2023,9 @@ impl Parser {
             self.bump();
             if *self.token == token::LPAREN {
                 let name_idx_lo = *name_idx;
-                let ms = self.parse_matcher_subseq(
-                    name_idx,
-                    token::LPAREN,
-                    token::RPAREN
-                );
+                self.bump();
+                let ms = self.parse_matcher_subseq_upto(name_idx,
+                                                        &token::RPAREN);
                 if ms.len() == 0u {
                     self.fatal("repetition body must be nonempty");
                 }
@@ -1987,9 +2040,7 @@ impl Parser {
                 m
             }
         } else {
-            let m = match_tok(copy *self.token);
-            self.bump();
-            m
+            match_tok(self.bump_and_get())
         };
 
         return spanned(lo, self.span.hi, m);
@@ -2094,16 +2145,15 @@ impl Parser {
     // parse an expression of binops of at least min_prec precedence
     pub fn parse_more_binops(&self, lhs: @expr, min_prec: uint) -> @expr {
         if self.expr_is_complete(lhs) { return lhs; }
-        let peeked = copy *self.token;
-        if peeked == token::BINOP(token::OR) &&
+        if token::BINOP(token::OR) == *self.token &&
             (*self.restriction == RESTRICT_NO_BAR_OP ||
              *self.restriction == RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) {
             lhs
-        } else if peeked == token::OROR &&
+        } else if token::OROR == *self.token &&
             *self.restriction == RESTRICT_NO_BAR_OR_DOUBLEBAR_OP {
             lhs
         } else {
-            let cur_opt = token_to_binop(peeked);
+            let cur_opt = token_to_binop(self.token);
             match cur_opt {
                 Some(cur_op) => {
                     let cur_prec = operator_prec(cur_op);
@@ -2290,23 +2340,31 @@ impl Parser {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
-                let args = vec::append(copy *args, [last_arg]);
+                let args = vec::append((*args).clone(), [last_arg]);
                 self.mk_expr(lo, block.span.hi, expr_call(f, args, sugar))
             }
             expr_method_call(_, f, i, ref tps, ref args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
-                let args = vec::append(copy *args, [last_arg]);
+                let args = vec::append((*args).clone(), [last_arg]);
                 self.mk_expr(lo, block.span.hi,
-                             self.mk_method_call(f, i, copy *tps, args, sugar))
+                             self.mk_method_call(f,
+                                                 i,
+                                                 (*tps).clone(),
+                                                 args,
+                                                 sugar))
             }
             expr_field(f, i, ref tps) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 self.mk_expr(lo, block.span.hi,
-                             self.mk_method_call(f, i, copy *tps, ~[last_arg], sugar))
+                             self.mk_method_call(f,
+                                                 i,
+                                                 (*tps).clone(),
+                                                 ~[last_arg],
+                                                 sugar))
             }
             expr_path(*) | expr_call(*) | expr_method_call(*) |
                 expr_paren(*) => {
@@ -2343,7 +2401,7 @@ impl Parser {
         let is_loop_header =
             *self.token == token::LBRACE
             || (is_ident(&*self.token)
-                && self.look_ahead(1) == token::LBRACE);
+                && self.look_ahead(1, |t| *t == token::LBRACE));
 
         if is_loop_header {
             // This is a loop body
@@ -2373,11 +2431,10 @@ impl Parser {
 
     // For distingishing between record literals and blocks
     fn looking_at_record_literal(&self) -> bool {
-        let lookahead = self.look_ahead(1);
         *self.token == token::LBRACE &&
-            (token::is_keyword(keywords::Mut, &lookahead) ||
-             (is_plain_ident(&lookahead) &&
-              self.look_ahead(2) == token::COLON))
+            (self.look_ahead(1, |t| token::is_keyword(keywords::Mut, t)) ||
+             (self.look_ahead(1, |t| token::is_plain_ident(t)) &&
+              self.look_ahead(2, |t| *t == token::COLON)))
     }
 
     fn parse_match_expr(&self) -> @expr {
@@ -2388,7 +2445,9 @@ impl Parser {
         while *self.token != token::RBRACE {
             let pats = self.parse_pats();
             let mut guard = None;
-            if self.eat_keyword(keywords::If) { guard = Some(self.parse_expr()); }
+            if self.eat_keyword(keywords::If) {
+                guard = Some(self.parse_expr());
+            }
             self.expect(&token::FAT_ARROW);
             let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
 
@@ -2554,12 +2613,21 @@ impl Parser {
         maybe_whole!(self, nt_pat);
 
         let lo = self.span.lo;
-        let mut hi = self.span.hi;
+        let mut hi;
         let pat;
-        match /*bad*/ copy *self.token {
+        match *self.token {
             // parse _
-          token::UNDERSCORE => { self.bump(); pat = pat_wild; }
-            // parse @pat
+          token::UNDERSCORE => {
+            self.bump();
+            pat = pat_wild;
+            hi = self.last_span.hi;
+            return @ast::pat {
+                id: self.get_id(),
+                node: pat,
+                span: mk_sp(lo, hi)
+            }
+          }
+          // parse @pat
           token::AT => {
             self.bump();
             let sub = self.parse_pat();
@@ -2580,6 +2648,12 @@ impl Parser {
               }
               _ => pat_box(sub)
             };
+            hi = self.last_span.hi;
+            return @ast::pat {
+                id: self.get_id(),
+                node: pat,
+                span: mk_sp(lo, hi)
+            }
           }
           token::TILDE => {
             // parse ~pat
@@ -2602,6 +2676,12 @@ impl Parser {
               }
               _ => pat_uniq(sub)
             };
+            hi = self.last_span.hi;
+            return @ast::pat {
+                id: self.get_id(),
+                node: pat,
+                span: mk_sp(lo, hi)
+            }
           }
           token::BINOP(token::AND) => {
               // parse &pat
@@ -2623,7 +2703,13 @@ impl Parser {
                       pat_lit(vst)
                   }
               _ => pat_region(sub)
-              };
+            };
+            hi = self.last_span.hi;
+            return @ast::pat {
+                id: self.get_id(),
+                node: pat,
+                span: mk_sp(lo, hi)
+            }
           }
           token::LBRACE => {
             self.bump();
@@ -2632,6 +2718,12 @@ impl Parser {
             self.bump();
             self.obsolete(*self.span, ObsoleteRecordPattern);
             pat = pat_wild;
+            hi = self.last_span.hi;
+            return @ast::pat {
+                id: self.get_id(),
+                node: pat,
+                span: mk_sp(lo, hi)
+            }
           }
           token::LPAREN => {
             // parse (pat,pat,pat,...) as tuple
@@ -2646,7 +2738,7 @@ impl Parser {
                 pat = pat_lit(expr);
             } else {
                 let mut fields = ~[self.parse_pat()];
-                if self.look_ahead(1) != token::RPAREN {
+                if self.look_ahead(1, |t| *t != token::RPAREN) {
                     while *self.token == token::COMMA {
                         self.bump();
                         fields.push(self.parse_pat());
@@ -2657,6 +2749,12 @@ impl Parser {
                 self.expect(&token::RPAREN);
                 pat = pat_tup(fields);
             }
+            hi = self.last_span.hi;
+            return @ast::pat {
+                id: self.get_id(),
+                node: pat,
+                span: mk_sp(lo, hi)
+            }
           }
           token::LBRACKET => {
             // parse [pat,pat,...] as vector pattern
@@ -2666,118 +2764,130 @@ impl Parser {
             hi = self.span.hi;
             self.expect(&token::RBRACKET);
             pat = ast::pat_vec(before, slice, after);
+            hi = self.last_span.hi;
+            return @ast::pat {
+                id: self.get_id(),
+                node: pat,
+                span: mk_sp(lo, hi)
+            }
           }
-          ref tok => {
-            if !is_ident_or_path(tok)
+          _ => {}
+        }
+
+        let tok = self.token;
+        if !is_ident_or_path(tok)
                 || self.is_keyword(keywords::True)
-                || self.is_keyword(keywords::False)
-            {
-                // Parse an expression pattern or exp .. exp.
-                //
-                // These expressions are limited to literals (possibly
-                // preceded by unary-minus) or identifiers.
-                let val = self.parse_literal_maybe_minus();
-                if self.eat(&token::DOTDOT) {
-                    let end = if is_ident_or_path(tok) {
-                        let path = self.parse_path_with_tps(true);
-                        let hi = self.span.hi;
-                        self.mk_expr(lo, hi, expr_path(path))
-                    } else {
-                        self.parse_literal_maybe_minus()
-                    };
-                    pat = pat_range(val, end);
+                || self.is_keyword(keywords::False) {
+            // Parse an expression pattern or exp .. exp.
+            //
+            // These expressions are limited to literals (possibly
+            // preceded by unary-minus) or identifiers.
+            let val = self.parse_literal_maybe_minus();
+            if self.eat(&token::DOTDOT) {
+                let end = if is_ident_or_path(tok) {
+                    let path = self.parse_path_with_tps(true);
+                    let hi = self.span.hi;
+                    self.mk_expr(lo, hi, expr_path(path))
                 } else {
-                    pat = pat_lit(val);
-                }
-            } else if self.eat_keyword(keywords::Ref) {
-                // parse ref pat
-                let mutbl = self.parse_mutability();
-                pat = self.parse_pat_ident(bind_by_ref(mutbl));
-            } else if self.eat_keyword(keywords::Copy) {
-                // parse copy pat
-                self.obsolete(*self.span, ObsoletePatternCopyKeyword);
-                pat = self.parse_pat_ident(bind_infer);
+                    self.parse_literal_maybe_minus()
+                };
+                pat = pat_range(val, end);
             } else {
-                let can_be_enum_or_struct;
-                match self.look_ahead(1) {
+                pat = pat_lit(val);
+            }
+        } else if self.eat_keyword(keywords::Ref) {
+            // parse ref pat
+            let mutbl = self.parse_mutability();
+            pat = self.parse_pat_ident(bind_by_ref(mutbl));
+        } else if self.eat_keyword(keywords::Copy) {
+            // parse copy pat
+            self.obsolete(*self.span, ObsoletePatternCopyKeyword);
+            pat = self.parse_pat_ident(bind_infer);
+        } else {
+            let can_be_enum_or_struct = do self.look_ahead(1) |t| {
+                match *t {
                     token::LPAREN | token::LBRACKET | token::LT |
-                    token::LBRACE | token::MOD_SEP =>
-                        can_be_enum_or_struct = true,
-                    _ =>
-                        can_be_enum_or_struct = false
+                    token::LBRACE | token::MOD_SEP => true,
+                    _ => false,
                 }
+            };
 
-                if self.look_ahead(1) == token::DOTDOT {
-                    let start = self.parse_expr_res(RESTRICT_NO_BAR_OP);
-                    self.eat(&token::DOTDOT);
-                    let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
-                    pat = pat_range(start, end);
+            if self.look_ahead(1, |t| *t == token::DOTDOT) {
+                let start = self.parse_expr_res(RESTRICT_NO_BAR_OP);
+                self.eat(&token::DOTDOT);
+                let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
+                pat = pat_range(start, end);
+            } else if is_plain_ident(&*self.token) && !can_be_enum_or_struct {
+                let name = self.parse_path_without_tps();
+                let sub;
+                if self.eat(&token::AT) {
+                    // parse foo @ pat
+                    sub = Some(self.parse_pat());
+                } else {
+                    // or just foo
+                    sub = None;
                 }
-                else if is_plain_ident(&*self.token) && !can_be_enum_or_struct {
-                    let name = self.parse_path_without_tps();
-                    let sub;
-                    if self.eat(&token::AT) {
-                        // parse foo @ pat
-                        sub = Some(self.parse_pat());
-                    } else {
-                        // or just foo
-                        sub = None;
+                pat = pat_ident(bind_infer, name, sub);
+            } else {
+                // parse an enum pat
+                let enum_path = self.parse_path_with_tps(true);
+                match *self.token {
+                    token::LBRACE => {
+                        self.bump();
+                        let (fields, etc) =
+                            self.parse_pat_fields();
+                        self.bump();
+                        pat = pat_struct(enum_path, fields, etc);
                     }
-                    pat = pat_ident(bind_infer, name, sub);
-                } else {
-                    // parse an enum pat
-                    let enum_path = self.parse_path_with_tps(true);
-                    match *self.token {
-                        token::LBRACE => {
-                            self.bump();
-                            let (fields, etc) =
-                                self.parse_pat_fields();
-                            self.bump();
-                            pat = pat_struct(enum_path, fields, etc);
-                        }
-                        _ => {
-                            let mut args: ~[@pat] = ~[];
-                            match *self.token {
-                              token::LPAREN => match self.look_ahead(1u) {
-                                token::BINOP(token::STAR) => {
-                                    // This is a "top constructor only" pat
-                                      self.bump(); self.bump();
-                                      self.expect(&token::RPAREN);
-                                      pat = pat_enum(enum_path, None);
-                                  }
-                                _ => {
-                                    args = self.parse_unspanned_seq(
-                                        &token::LPAREN,
-                                        &token::RPAREN,
-                                        seq_sep_trailing_disallowed(
-                                            token::COMMA
-                                        ),
-                                        |p| p.parse_pat()
-                                    );
-                                    pat = pat_enum(enum_path, Some(args));
-                                  }
-                              },
-                              _ => {
-                                  if enum_path.idents.len()==1u {
-                                      // it could still be either an enum
-                                      // or an identifier pattern, resolve
-                                      // will sort it out:
-                                      pat = pat_ident(bind_infer,
-                                                      enum_path,
-                                                      None);
-                                  } else {
-                                      pat = pat_enum(enum_path, Some(args));
-                                  }
-                              }
+                    _ => {
+                        let mut args: ~[@pat] = ~[];
+                        match *self.token {
+                          token::LPAREN => {
+                            let is_star = do self.look_ahead(1) |t| {
+                                match *t {
+                                    token::BINOP(token::STAR) => true,
+                                    _ => false,
+                                }
+                            };
+                            if is_star {
+                                // This is a "top constructor only" pat
+                                self.bump();
+                                self.bump();
+                                self.expect(&token::RPAREN);
+                                pat = pat_enum(enum_path, None);
+                            } else {
+                                args = self.parse_unspanned_seq(
+                                    &token::LPAREN,
+                                    &token::RPAREN,
+                                    seq_sep_trailing_disallowed(token::COMMA),
+                                    |p| p.parse_pat()
+                                );
+                                pat = pat_enum(enum_path, Some(args));
                             }
+                          },
+                          _ => {
+                              if enum_path.idents.len()==1u {
+                                  // it could still be either an enum
+                                  // or an identifier pattern, resolve
+                                  // will sort it out:
+                                  pat = pat_ident(bind_infer,
+                                                  enum_path,
+                                                  None);
+                              } else {
+                                  pat = pat_enum(enum_path, Some(args));
+                              }
+                          }
                         }
                     }
                 }
             }
-            hi = self.last_span.hi;
-          }
         }
-        @ast::pat { id: self.get_id(), node: pat, span: mk_sp(lo, hi) }
+        hi = self.last_span.hi;
+        @ast::pat {
+            id: self.get_id(),
+            node: pat,
+            span: mk_sp(lo, hi),
+        }
     }
 
     // parse ident or ident @ pat
@@ -2878,23 +2988,22 @@ impl Parser {
     pub fn parse_stmt(&self, item_attrs: ~[attribute]) -> @stmt {
         maybe_whole!(self, nt_stmt);
 
-        fn check_expected_item(p: &Parser, current_attrs: &[attribute]) {
+        fn check_expected_item(p: &Parser, found_attrs: bool) {
             // If we have attributes then we should have an item
-            if !current_attrs.is_empty() {
-                p.span_err(*p.last_span,
-                           "expected item after attributes");
+            if found_attrs {
+                p.span_err(*p.last_span, "expected item after attributes");
             }
         }
 
         let lo = self.span.lo;
         if self.is_keyword(keywords::Let) {
-            check_expected_item(self, item_attrs);
+            check_expected_item(self, !item_attrs.is_empty());
             self.expect_keyword(keywords::Let);
             let decl = self.parse_let();
             return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id()));
         } else if is_ident(&*self.token)
             && !token::is_any_keyword(self.token)
-            && self.look_ahead(1) == token::NOT {
+            && self.look_ahead(1, |t| *t == token::NOT) {
             // parse a macro invocation. Looks like there's serious
             // overlap here; if this clause doesn't catch it (and it
             // won't, for brace-delimited macros) it will fall through
@@ -2908,7 +3017,7 @@ impl Parser {
             // somewhat awkward... and probably undocumented. Of course,
             // I could just be wrong.
 
-            check_expected_item(self, item_attrs);
+            check_expected_item(self, !item_attrs.is_empty());
 
             // Potential trouble: if we allow macros with paths instead of
             // idents, we'd need to look ahead past the whole path here...
@@ -2944,8 +3053,8 @@ impl Parser {
             }
 
         } else {
-            match self.parse_item_or_view_item(/*bad*/ copy item_attrs,
-                                                           false) {
+            let found_attrs = !item_attrs.is_empty();
+            match self.parse_item_or_view_item(item_attrs, false) {
                 iovi_item(i) => {
                     let hi = i.span.hi;
                     let decl = @spanned(lo, hi, decl_item(i));
@@ -2958,10 +3067,10 @@ impl Parser {
                 iovi_foreign_item(_) => {
                     self.fatal("foreign items are not allowed here");
                 }
-                iovi_none() => { /* fallthrough */ }
+                iovi_none(_) => { /* fallthrough */ }
             }
 
-            check_expected_item(self, item_attrs);
+            check_expected_item(self, found_attrs);
 
             // Remainder are line-expr stmts.
             let e = self.parse_expr_res(RESTRICT_STMT_EXPR);
@@ -3056,48 +3165,66 @@ impl Parser {
                     match stmt.node {
                         stmt_expr(e, stmt_id) => {
                             // expression without semicolon
-                            match copy *self.token {
+                            let has_semi;
+                            match *self.token {
                                 token::SEMI => {
-                                    self.bump();
-                                    stmts.push(@codemap::spanned {
-                                        node: stmt_semi(e, stmt_id),
-                                        .. copy *stmt});
+                                    has_semi = true;
                                 }
                                 token::RBRACE => {
+                                    has_semi = false;
                                     expr = Some(e);
                                 }
-                                t => {
+                                ref t => {
+                                    has_semi = false;
                                     if classify::stmt_ends_with_semi(stmt) {
                                         self.fatal(
                                             fmt!(
                                                 "expected `;` or `}` after \
                                                  expression but found `%s`",
-                                                self.token_to_str(&t)
+                                                self.token_to_str(t)
                                             )
                                         );
                                     }
                                     stmts.push(stmt);
                                 }
                             }
+
+                            if has_semi {
+                                self.bump();
+                                stmts.push(@codemap::spanned {
+                                    node: stmt_semi(e, stmt_id),
+                                    span: stmt.span,
+                                });
+                            }
                         }
                         stmt_mac(ref m, _) => {
                             // statement macro; might be an expr
+                            let has_semi;
                             match *self.token {
                                 token::SEMI => {
-                                    self.bump();
-                                    stmts.push(@codemap::spanned {
-                                        node: stmt_mac(copy *m, true),
-                                        .. copy *stmt});
+                                    has_semi = true;
                                 }
                                 token::RBRACE => {
                                     // if a block ends in `m!(arg)` without
                                     // a `;`, it must be an expr
+                                    has_semi = false;
                                     expr = Some(
                                         self.mk_mac_expr(stmt.span.lo,
                                                          stmt.span.hi,
-                                                         copy m.node));
+                                                         m.node.clone()));
+                                }
+                                _ => {
+                                    has_semi = false;
+                                    stmts.push(stmt);
                                 }
-                                _ => { stmts.push(stmt); }
+                            }
+
+                            if has_semi {
+                                self.bump();
+                                stmts.push(@codemap::spanned {
+                                    node: stmt_mac((*m).clone(), true),
+                                    span: stmt.span,
+                                });
                             }
                         }
                         _ => { // all other kinds of statements:
@@ -3302,10 +3429,10 @@ impl Parser {
             p: &Parser
         ) -> ast::explicit_self_ {
             // We need to make sure it isn't a mode or a type
-            if token::is_keyword(keywords::Self, &p.look_ahead(1)) ||
-                ((token::is_keyword(keywords::Const, &p.look_ahead(1)) ||
-                  token::is_keyword(keywords::Mut, &p.look_ahead(1))) &&
-                 token::is_keyword(keywords::Self, &p.look_ahead(2))) {
+            if p.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) ||
+                ((p.look_ahead(1, |t| token::is_keyword(keywords::Const, t)) ||
+                  p.look_ahead(1, |t| token::is_keyword(keywords::Mut, t))) &&
+                 p.look_ahead(2, |t| token::is_keyword(keywords::Self, t))) {
 
                 p.bump();
                 let mutability = p.parse_mutability();
@@ -3326,25 +3453,30 @@ impl Parser {
             //
             // We already know that the current token is `&`.
 
-            if (token::is_keyword(keywords::Self, &this.look_ahead(1))) {
+            if this.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
                 this.bump();
                 this.expect_self_ident();
                 sty_region(None, m_imm)
-            } else if (this.token_is_mutability(&this.look_ahead(1)) &&
-                       token::is_keyword(keywords::Self, &this.look_ahead(2))) {
+            } else if this.look_ahead(1, |t| this.token_is_mutability(t)) &&
+                    this.look_ahead(2,
+                                    |t| token::is_keyword(keywords::Self,
+                                                          t)) {
                 this.bump();
                 let mutability = this.parse_mutability();
                 this.expect_self_ident();
                 sty_region(None, mutability)
-            } else if (this.token_is_lifetime(&this.look_ahead(1)) &&
-                       token::is_keyword(keywords::Self, &this.look_ahead(2))) {
+            } else if this.look_ahead(1, |t| this.token_is_lifetime(t)) &&
+                       this.look_ahead(2,
+                                       |t| token::is_keyword(keywords::Self,
+                                                             t)) {
                 this.bump();
                 let lifetime = this.parse_lifetime();
                 this.expect_self_ident();
                 sty_region(Some(lifetime), m_imm)
-            } else if (this.token_is_lifetime(&this.look_ahead(1)) &&
-                       this.token_is_mutability(&this.look_ahead(2)) &&
-                       token::is_keyword(keywords::Self, &this.look_ahead(3))) {
+            } else if this.look_ahead(1, |t| this.token_is_lifetime(t)) &&
+                      this.look_ahead(2, |t| this.token_is_mutability(t)) &&
+                      this.look_ahead(3, |t| token::is_keyword(keywords::Self,
+                                                               t)) {
                 this.bump();
                 let lifetime = this.parse_lifetime();
                 let mutability = this.parse_mutability();
@@ -3563,7 +3695,7 @@ impl Parser {
             let opt_trait_ref = match ty.node {
                 ty_path(ref path, None, node_id) => {
                     Some(trait_ref {
-                        path: /* bad */ copy *path,
+                        path: /* bad */ (*path).clone(),
                         ref_id: node_id
                     })
                 }
@@ -3768,8 +3900,10 @@ impl Parser {
 
     // given a termination token and a vector of already-parsed
     // attributes (of length 0 or 1), parse all of the items in a module
-    fn parse_mod_items(&self, term: token::Token,
-                       first_item_attrs: ~[attribute]) -> _mod {
+    fn parse_mod_items(&self,
+                       term: token::Token,
+                       first_item_attrs: ~[attribute])
+                       -> _mod {
         // parse all of the items up to closing or an attribute.
         // view items are legal here.
         let ParsedItemsAndViewItems {
@@ -3777,8 +3911,7 @@ impl Parser {
             view_items: view_items,
             items: starting_items,
             _
-        } = self.parse_items_and_view_items(first_item_attrs,
-                                            true, true);
+        } = self.parse_items_and_view_items(first_item_attrs, true, true);
         let mut items: ~[@item] = starting_items;
         let attrs_remaining_len = attrs_remaining.len();
 
@@ -3793,25 +3926,19 @@ impl Parser {
             }
             debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)",
                    attrs);
-            match self.parse_item_or_view_item(
-                /*bad*/ copy attrs,
-                true // macros allowed
-            ) {
+            match self.parse_item_or_view_item(attrs,
+                                               true /* macros allowed */) {
               iovi_item(item) => items.push(item),
               iovi_view_item(view_item) => {
-                self.span_fatal(view_item.span, "view items must be  declared at the top of the \
-                                                 module");
+                self.span_fatal(view_item.span,
+                                "view items must be declared at the top of \
+                                 the module");
               }
               _ => {
-                self.fatal(
-                    fmt!(
-                        "expected item but found `%s`",
-                        self.this_token_to_str()
-                    )
-                );
+                self.fatal(fmt!("expected item but found `%s`",
+                                self.this_token_to_str()));
               }
             }
-            debug!("parse_mod_items: attrs=%?", attrs);
         }
 
         if first && attrs_remaining_len > 0u {
@@ -3834,7 +3961,7 @@ impl Parser {
     }
 
     // parse a `mod <foo> { ... }` or `mod <foo>;` item
-    fn parse_item_mod(&self, outer_attrs: ~[ast::attribute]) -> item_info {
+    fn parse_item_mod(&self, outer_attrs: &[ast::attribute]) -> item_info {
         let id_span = *self.span;
         let id = self.parse_ident();
         if *self.token == token::SEMI {
@@ -3853,7 +3980,7 @@ impl Parser {
         }
     }
 
-    fn push_mod_path(&self, id: ident, attrs: ~[ast::attribute]) {
+    fn push_mod_path(&self, id: ident, attrs: &[ast::attribute]) {
         let default_path = token::interner_get(id.name);
         let file_path = match ::attr::first_attr_value_str_by_name(
             attrs, "path") {
@@ -3869,17 +3996,18 @@ impl Parser {
     }
 
     // read a module from a source file.
-    fn eval_src_mod(&self, id: ast::ident,
-                    outer_attrs: ~[ast::attribute],
-                    id_sp: span) -> (ast::item_, ~[ast::attribute]) {
-
+    fn eval_src_mod(&self,
+                    id: ast::ident,
+                    outer_attrs: &[ast::attribute],
+                    id_sp: span)
+                    -> (ast::item_, ~[ast::attribute]) {
         let prefix = Path(self.sess.cm.span_to_filename(*self.span));
         let prefix = prefix.dir_path();
         let mod_path_stack = &*self.mod_path_stack;
         let mod_path = Path(".").push_many(*mod_path_stack);
         let default_path = token::interner_get(id.name).to_owned() + ".rs";
         let file_path = match ::attr::first_attr_value_str_by_name(
-            outer_attrs, "path") {
+                outer_attrs, "path") {
             Some(d) => {
                 let path = Path(d);
                 if !path.is_absolute {
@@ -3891,14 +4019,17 @@ impl Parser {
             None => mod_path.push(default_path)
         };
 
-        self.eval_src_mod_from_path(prefix, file_path,
-                                    outer_attrs, id_sp)
+        self.eval_src_mod_from_path(prefix,
+                                    file_path,
+                                    outer_attrs.to_owned(),
+                                    id_sp)
     }
 
-    fn eval_src_mod_from_path(&self, prefix: Path, path: Path,
+    fn eval_src_mod_from_path(&self,
+                              prefix: Path,
+                              path: Path,
                               outer_attrs: ~[ast::attribute],
-                              id_sp: span
-                             ) -> (ast::item_, ~[ast::attribute]) {
+                              id_sp: span) -> (ast::item_, ~[ast::attribute]) {
 
         let full_path = if path.is_absolute {
             path
@@ -3924,8 +4055,10 @@ impl Parser {
         self.sess.included_mod_stack.push(full_path.clone());
 
         let p0 =
-            new_sub_parser_from_file(self.sess, copy self.cfg,
-                                     &full_path, id_sp);
+            new_sub_parser_from_file(self.sess,
+                                     self.cfg.clone(),
+                                     &full_path,
+                                     id_sp);
         let (inner, next) = p0.parse_inner_attrs_and_next();
         let mod_attrs = vec::append(outer_attrs, inner);
         let first_item_outer_attrs = next;
@@ -4074,7 +4207,7 @@ impl Parser {
 
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
                                           item_foreign_mod(m), visibility,
-                                          maybe_append(/*bad*/ copy attrs,
+                                          maybe_append(attrs,
                                                        Some(inner))));
         }
 
@@ -4087,7 +4220,7 @@ impl Parser {
         self.expect(&token::SEMI);
         iovi_view_item(ast::view_item {
             node: view_item_extern_mod(ident, metadata, self.get_id()),
-            attrs: copy attrs,
+            attrs: attrs,
             vis: visibility,
             span: mk_sp(lo, self.last_span.hi)
         })
@@ -4253,8 +4386,8 @@ impl Parser {
         }
     }
 
-    fn fn_expr_lookahead(&self, tok: token::Token) -> bool {
-        match tok {
+    fn fn_expr_lookahead(&self, tok: &token::Token) -> bool {
+        match *tok {
           token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true,
           _ => false
         }
@@ -4304,11 +4437,10 @@ impl Parser {
     // flags; on failure, return iovi_none.
     // NB: this function no longer parses the items inside an
     // extern mod.
-    fn parse_item_or_view_item(
-        &self,
-        attrs: ~[attribute],
-        macros_allowed: bool
-    ) -> item_or_view_item {
+    fn parse_item_or_view_item(&self,
+                               attrs: ~[attribute],
+                               macros_allowed: bool)
+                               -> item_or_view_item {
         maybe_whole!(iovi self, nt_item);
         let lo = self.span.lo;
 
@@ -4348,7 +4480,7 @@ impl Parser {
         // the rest are all guaranteed to be items:
         if (self.is_keyword(keywords::Const) ||
             (self.is_keyword(keywords::Static) &&
-             !token::is_keyword(keywords::Fn, &self.look_ahead(1)))) {
+             self.look_ahead(1, |t| !token::is_keyword(keywords::Fn, t)))) {
             // CONST / STATIC ITEM
             if self.is_keyword(keywords::Const) {
                 self.obsolete(*self.span, ObsoleteConstItem);
@@ -4360,7 +4492,7 @@ impl Parser {
                                           maybe_append(attrs, extra_attrs)));
         }
         if self.is_keyword(keywords::Fn) &&
-            !self.fn_expr_lookahead(self.look_ahead(1u)) {
+                self.look_ahead(1, |f| !self.fn_expr_lookahead(f)) {
             // FUNCTION ITEM
             self.bump();
             let (ident, item_, extra_attrs) =
@@ -4380,7 +4512,7 @@ impl Parser {
                                           maybe_append(attrs, extra_attrs)));
         }
         if self.is_keyword(keywords::Unsafe)
-            && self.look_ahead(1u) != token::LBRACE {
+            && self.look_ahead(1u, |t| *t != token::LBRACE) {
             // UNSAFE FUNCTION ITEM
             self.bump();
             self.expect_keyword(keywords::Fn);
@@ -4392,8 +4524,7 @@ impl Parser {
         }
         if self.eat_keyword(keywords::Mod) {
             // MODULE ITEM
-            let (ident, item_, extra_attrs) =
-                self.parse_item_mod(/*bad*/ copy attrs);
+            let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
@@ -4438,11 +4569,10 @@ impl Parser {
     }
 
     // parse a foreign item; on failure, return iovi_none.
-    fn parse_foreign_item(
-        &self,
-        attrs: ~[attribute],
-        macros_allowed: bool
-    ) -> item_or_view_item {
+    fn parse_foreign_item(&self,
+                          attrs: ~[attribute],
+                          macros_allowed: bool)
+                          -> item_or_view_item {
         maybe_whole!(iovi self, nt_item);
         let lo = self.span.lo;
 
@@ -4471,10 +4601,10 @@ impl Parser {
         visibility : visibility
     ) -> item_or_view_item {
         if macros_allowed && !token::is_any_keyword(self.token)
-                && self.look_ahead(1) == token::NOT
-                && (is_plain_ident(&self.look_ahead(2))
-                    || self.look_ahead(2) == token::LPAREN
-                    || self.look_ahead(2) == token::LBRACE) {
+                && self.look_ahead(1, |t| *t == token::NOT)
+                && (self.look_ahead(2, |t| is_plain_ident(t))
+                    || self.look_ahead(2, |t| *t == token::LPAREN)
+                    || self.look_ahead(2, |t| *t == token::LBRACE)) {
             // MACRO INVOCATION ITEM
             if attrs.len() > 0 {
                 self.fatal("attrs on macros are not yet supported");
@@ -4496,12 +4626,10 @@ impl Parser {
             let tts = match *self.token {
                 token::LPAREN | token::LBRACE => {
                     let ket = token::flip_delimiter(&*self.token);
-                    self.parse_unspanned_seq(
-                        &copy *self.token,
-                        &ket,
-                        seq_sep_none(),
-                        |p| p.parse_token_tree()
-                    )
+                    self.bump();
+                    self.parse_seq_to_end(&ket,
+                                          seq_sep_none(),
+                                          |p| p.parse_token_tree())
                 }
                 _ => self.fatal("expected open delimiter")
             };
@@ -4526,12 +4654,12 @@ impl Parser {
             s.push_char('`');
             self.span_fatal(*self.last_span, s);
         }
-        return iovi_none;
+        return iovi_none(attrs);
     }
 
     pub fn parse_item(&self, attrs: ~[attribute]) -> Option<@ast::item> {
         match self.parse_item_or_view_item(attrs, true) {
-            iovi_none =>
+            iovi_none(attrs) =>
                 None,
             iovi_view_item(_) =>
                 self.fatal("view items are not allowed here"),
@@ -4648,18 +4776,19 @@ impl Parser {
     }
 
     fn is_view_item(&self) -> bool {
-        let tok;
-        let next_tok;
         if !self.is_keyword(keywords::Pub) && !self.is_keyword(keywords::Priv) {
-            tok = copy *self.token;
-            next_tok = self.look_ahead(1);
+            token::is_keyword(keywords::Use, self.token)
+                || (token::is_keyword(keywords::Extern, self.token) &&
+                    self.look_ahead(1,
+                                    |t| token::is_keyword(keywords::Mod, t)))
         } else {
-            tok = self.look_ahead(1);
-            next_tok = self.look_ahead(2);
-        };
-        token::is_keyword(keywords::Use, &tok)
-            || (token::is_keyword(keywords::Extern, &tok) &&
-                token::is_keyword(keywords::Mod, &next_tok))
+            self.look_ahead(1, |t| token::is_keyword(keywords::Use, t))
+                || (self.look_ahead(1,
+                                    |t| token::is_keyword(keywords::Extern,
+                                                          t)) &&
+                    self.look_ahead(2,
+                                    |t| token::is_keyword(keywords::Mod, t)))
+        }
     }
 
     // parse a view item.
@@ -4706,11 +4835,14 @@ impl Parser {
         // view items, and regular items) ... except that because
         // of macros, I'd like to delay that entire check until later.
         loop {
-            match self.parse_item_or_view_item(/*bad*/ copy attrs,
-                                                           macros_allowed) {
-                iovi_none => {
-                    done = true;
-                    break;
+            match self.parse_item_or_view_item(attrs, macros_allowed) {
+                iovi_none(attrs) => {
+                    return ParsedItemsAndViewItems {
+                        attrs_remaining: attrs,
+                        view_items: view_items,
+                        items: items,
+                        foreign_items: ~[]
+                    }
                 }
                 iovi_view_item(view_item) => {
                     match view_item.node {
@@ -4740,23 +4872,24 @@ impl Parser {
         }
 
         // Next, parse items.
-        if !done {
-            loop {
-                match self.parse_item_or_view_item(/*bad*/ copy attrs,
-                                                   macros_allowed) {
-                    iovi_none => break,
-                    iovi_view_item(view_item) => {
-                        self.span_err(view_item.span,
-                                      "`use` and `extern mod` declarations must precede items");
-                    }
-                    iovi_item(item) => {
-                        items.push(item)
-                    }
-                    iovi_foreign_item(_) => {
-                        fail!();
-                    }
+        loop {
+            match self.parse_item_or_view_item(attrs, macros_allowed) {
+                iovi_none(returned_attrs) => {
+                    attrs = returned_attrs;
+                    break
+                }
+                iovi_view_item(view_item) => {
+                    attrs = self.parse_outer_attributes();
+                    self.span_err(view_item.span,
+                                  "`use` and `extern mod` declarations must precede items");
+                }
+                iovi_item(item) => {
+                    attrs = self.parse_outer_attributes();
+                    items.push(item)
+                }
+                iovi_foreign_item(_) => {
+                    fail!();
                 }
-                attrs = self.parse_outer_attributes();
             }
         }
 
@@ -4777,9 +4910,10 @@ impl Parser {
                                     self.parse_outer_attributes());
         let mut foreign_items = ~[];
         loop {
-            match self.parse_foreign_item(/*bad*/ copy attrs, macros_allowed) {
-                iovi_none => {
+            match self.parse_foreign_item(attrs, macros_allowed) {
+                iovi_none(returned_attrs) => {
                     if *self.token == token::RBRACE {
+                        attrs = returned_attrs;
                         break
                     }
                     self.unexpected();
@@ -4821,7 +4955,7 @@ impl Parser {
         @spanned(lo, self.span.lo,
                  ast::crate_ { module: m,
                                attrs: inner,
-                               config: copy self.cfg })
+                               config: self.cfg.clone() })
     }
 
     pub fn parse_str(&self) -> @str {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 01860c3ae99..8e14e56439e 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -20,7 +20,7 @@ use std::local_data;
 use std::rand;
 use std::rand::RngUtil;
 
-#[deriving(Encodable, Decodable, Eq, IterBytes)]
+#[deriving(Clone, Encodable, Decodable, Eq, IterBytes)]
 pub enum binop {
     PLUS,
     MINUS,
@@ -34,7 +34,7 @@ pub enum binop {
     SHR,
 }
 
-#[deriving(Encodable, Decodable, Eq, IterBytes)]
+#[deriving(Clone, Encodable, Decodable, Eq, IterBytes)]
 pub enum Token {
     /* Expression-operator symbols. */
     EQ,
@@ -95,7 +95,7 @@ pub enum Token {
     EOF,
 }
 
-#[deriving(Encodable, Decodable, Eq, IterBytes)]
+#[deriving(Clone, Encodable, Decodable, Eq, IterBytes)]
 /// For interpolation during macro expansion.
 pub enum nonterminal {
     nt_item(@ast::item),
@@ -350,8 +350,8 @@ pub mod special_idents {
  * Maps a token to a record specifying the corresponding binary
  * operator
  */
-pub fn token_to_binop(tok: Token) -> Option<ast::binop> {
-  match tok {
+pub fn token_to_binop(tok: &Token) -> Option<ast::binop> {
+  match *tok {
       BINOP(STAR)    => Some(ast::mul),
       BINOP(SLASH)   => Some(ast::div),
       BINOP(PERCENT) => Some(ast::rem),
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 8889fe91cc5..af2a4977082 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -64,19 +64,25 @@
 use std::io;
 use std::vec;
 
-#[deriving(Eq)]
-pub enum breaks { consistent, inconsistent, }
+#[deriving(Clone, Eq)]
+pub enum breaks {
+    consistent,
+    inconsistent,
+}
 
+#[deriving(Clone)]
 pub struct break_t {
     offset: int,
     blank_space: int
 }
 
+#[deriving(Clone)]
 pub struct begin_t {
     offset: int,
     breaks: breaks
 }
 
+#[deriving(Clone)]
 pub enum token {
     STRING(@str, int),
     BREAK(break_t),
@@ -476,11 +482,11 @@ impl Printer {
     pub fn print(&mut self, x: token, L: int) {
         debug!("print %s %d (remaining line space=%d)", tok_str(x), L,
                self.space);
-        debug!("%s", buf_str(copy self.token,
-                           copy self.size,
-                           self.left,
-                           self.right,
-                           6u));
+        debug!("%s", buf_str(self.token.clone(),
+                             self.size.clone(),
+                             self.left,
+                             self.right,
+                             6));
         match x {
           BEGIN(b) => {
             if L > self.space {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 5b4a6d15a12..2f0241967d9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -121,11 +121,15 @@ pub fn print_crate(cm: @CodeMap,
         s: pp::mk_printer(out, default_columns),
         cm: Some(cm),
         intr: intr,
-        comments: Some(copy cmnts),
+        comments: Some(cmnts),
         // If the code is post expansion, don't use the table of
         // literals, since it doesn't correspond with the literals
         // in the AST anymore.
-        literals: if is_expanded { None } else { Some(copy lits) },
+        literals: if is_expanded {
+            None
+        } else {
+            Some(lits)
+        },
         cur_cmnt_and_lit: @mut CurrentCommentAndLiteral {
             cur_cmnt: 0,
             cur_lit: 0
@@ -405,15 +409,19 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
         pclose(s);
       }
       ast::ty_bare_fn(f) => {
-          let generics = ast::Generics {lifetimes: copy f.lifetimes,
-                                        ty_params: opt_vec::Empty};
+          let generics = ast::Generics {
+            lifetimes: f.lifetimes.clone(),
+            ty_params: opt_vec::Empty
+          };
           print_ty_fn(s, Some(f.abis), None, &None,
                       f.purity, ast::Many, &f.decl, None, &None,
                       Some(&generics), None);
       }
       ast::ty_closure(f) => {
-          let generics = ast::Generics {lifetimes: copy f.lifetimes,
-                                        ty_params: opt_vec::Empty};
+          let generics = ast::Generics {
+            lifetimes: f.lifetimes.clone(),
+            ty_params: opt_vec::Empty
+          };
           print_ty_fn(s, None, Some(f.sigil), &f.region,
                       f.purity, f.onceness, &f.decl, None, &f.bounds,
                       Some(&generics), None);
@@ -1167,13 +1175,13 @@ pub fn print_expr(s: @ps, expr: &ast::expr) {
         pclose(s);
       }
       ast::expr_call(func, ref args, sugar) => {
-        let mut base_args = copy *args;
+        let mut base_args = (*args).clone();
         let blk = print_call_pre(s, sugar, &mut base_args);
         print_expr(s, func);
         print_call_post(s, sugar, &blk, &mut base_args);
       }
       ast::expr_method_call(_, func, ident, ref tys, ref args, sugar) => {
-        let mut base_args = copy *args;
+        let mut base_args = (*args).clone();
         let blk = print_call_pre(s, sugar, &mut base_args);
         print_expr(s, func);
         word(s.s, ".");
@@ -1798,12 +1806,10 @@ pub fn print_meta_item(s: @ps, item: &ast::meta_item) {
       ast::meta_list(name, ref items) => {
         word(s.s, name);
         popen(s);
-        commasep(
-            s,
-            consistent,
-            items.as_slice(),
-            |p, &i| print_meta_item(p, i)
-        );
+        commasep(s,
+                 consistent,
+                 items.as_slice(),
+                 |p, &i| print_meta_item(p, i));
         pclose(s);
       }
     }
@@ -2061,7 +2067,7 @@ pub fn next_lit(s: @ps, pos: BytePos) -> Option<comments::lit> {
     match s.literals {
       Some(ref lits) => {
         while s.cur_cmnt_and_lit.cur_lit < lits.len() {
-            let ltrl = /*bad*/ copy (*lits)[s.cur_cmnt_and_lit.cur_lit];
+            let ltrl = (*lits)[s.cur_cmnt_and_lit.cur_lit].clone();
             if ltrl.pos > pos { return None; }
             s.cur_cmnt_and_lit.cur_lit += 1u;
             if ltrl.pos == pos { return Some(ltrl); }
@@ -2148,8 +2154,10 @@ pub fn next_comment(s: @ps) -> Option<comments::cmnt> {
     match s.comments {
       Some(ref cmnts) => {
         if s.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
-            return Some(copy cmnts[s.cur_cmnt_and_lit.cur_cmnt]);
-        } else { return None::<comments::cmnt>; }
+            return Some(cmnts[s.cur_cmnt_and_lit.cur_cmnt].clone());
+        } else {
+            return None::<comments::cmnt>;
+        }
       }
       _ => return None::<comments::cmnt>
     }
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index 3cdc4fd0fa1..3d2e0632a33 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -21,7 +21,7 @@ pub struct Interner<T> {
 }
 
 // when traits can extend traits, we should extend index<uint,T> to get []
-impl<T:Eq + IterBytes + Hash + Freeze + Copy> Interner<T> {
+impl<T:Eq + IterBytes + Hash + Freeze + Clone> Interner<T> {
     pub fn new() -> Interner<T> {
         Interner {
             map: @mut HashMap::new(),
@@ -31,7 +31,9 @@ impl<T:Eq + IterBytes + Hash + Freeze + Copy> Interner<T> {
 
     pub fn prefill(init: &[T]) -> Interner<T> {
         let rv = Interner::new();
-        for init.iter().advance |v| { rv.intern(copy *v); }
+        for init.iter().advance |v| {
+            rv.intern((*v).clone());
+        }
         rv
     }
 
@@ -43,7 +45,7 @@ impl<T:Eq + IterBytes + Hash + Freeze + Copy> Interner<T> {
 
         let vect = &mut *self.vect;
         let new_idx = vect.len();
-        self.map.insert(copy val, new_idx);
+        self.map.insert(val.clone(), new_idx);
         vect.push(val);
         new_idx
     }
@@ -58,7 +60,9 @@ impl<T:Eq + IterBytes + Hash + Freeze + Copy> Interner<T> {
         new_idx
     }
 
-    pub fn get(&self, idx: uint) -> T { copy self.vect[idx] }
+    pub fn get(&self, idx: uint) -> T {
+        self.vect[idx].clone()
+    }
 
     pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() }
 
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 5c5d154a445..d68958ffa77 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -59,7 +59,7 @@ pub fn generics_of_fn(fk: &fn_kind) -> Generics {
     match *fk {
         fk_item_fn(_, generics, _, _) |
         fk_method(_, generics, _) => {
-            copy *generics
+            (*generics).clone()
         }
         fk_anon(*) | fk_fn_block(*) => {
             Generics {
@@ -94,7 +94,7 @@ pub struct Visitor<E> {
 
 pub type visitor<E> = @Visitor<E>;
 
-pub fn default_visitor<E: Copy>() -> visitor<E> {
+pub fn default_visitor<E:Clone>() -> visitor<E> {
     return @Visitor {
         visit_mod: |a,b,c,d|visit_mod::<E>(a, b, c, d),
         visit_view_item: |a,b|visit_view_item::<E>(a, b),
@@ -118,35 +118,42 @@ pub fn default_visitor<E: Copy>() -> visitor<E> {
     };
 }
 
-pub fn visit_crate<E: Copy>(c: &crate, (e, v): (E, vt<E>)) {
+pub fn visit_crate<E:Clone>(c: &crate, (e, v): (E, vt<E>)) {
     (v.visit_mod)(&c.node.module, c.span, crate_node_id, (e, v));
 }
 
-pub fn visit_mod<E: Copy>(m: &_mod, _sp: span, _id: node_id, (e, v): (E, vt<E>)) {
-    for m.view_items.iter().advance |vi| { (v.visit_view_item)(vi, (copy e, v)); }
-    for m.items.iter().advance |i| { (v.visit_item)(*i, (copy e, v)); }
+pub fn visit_mod<E:Clone>(m: &_mod,
+                          _sp: span,
+                          _id: node_id,
+                          (e, v): (E, vt<E>)) {
+    for m.view_items.iter().advance |vi| {
+        (v.visit_view_item)(vi, (e.clone(), v));
+    }
+    for m.items.iter().advance |i| {
+        (v.visit_item)(*i, (e.clone(), v));
+    }
 }
 
 pub fn visit_view_item<E>(_vi: &view_item, (_e, _v): (E, vt<E>)) { }
 
-pub fn visit_local<E: Copy>(loc: &local, (e, v): (E, vt<E>)) {
-    (v.visit_pat)(loc.node.pat, (copy e, v));
-    (v.visit_ty)(&loc.node.ty, (copy e, v));
+pub fn visit_local<E:Clone>(loc: &local, (e, v): (E, vt<E>)) {
+    (v.visit_pat)(loc.node.pat, (e.clone(), v));
+    (v.visit_ty)(&loc.node.ty, (e.clone(), v));
     match loc.node.init {
       None => (),
       Some(ex) => (v.visit_expr)(ex, (e, v))
     }
 }
 
-fn visit_trait_ref<E: Copy>(tref: &ast::trait_ref, (e, v): (E, vt<E>)) {
+fn visit_trait_ref<E:Clone>(tref: &ast::trait_ref, (e, v): (E, vt<E>)) {
     visit_path(&tref.path, (e, v));
 }
 
-pub fn visit_item<E: Copy>(i: &item, (e, v): (E, vt<E>)) {
+pub fn visit_item<E:Clone>(i: &item, (e, v): (E, vt<E>)) {
     match i.node {
         item_static(ref t, _, ex) => {
-            (v.visit_ty)(t, (copy e, v));
-            (v.visit_expr)(ex, (copy e, v));
+            (v.visit_ty)(t, (e.clone(), v));
+            (v.visit_expr)(ex, (e.clone(), v));
         }
         item_fn(ref decl, purity, abi, ref generics, ref body) => {
             (v.visit_fn)(
@@ -166,15 +173,19 @@ pub fn visit_item<E: Copy>(i: &item, (e, v): (E, vt<E>)) {
         }
         item_mod(ref m) => (v.visit_mod)(m, i.span, i.id, (e, v)),
         item_foreign_mod(ref nm) => {
-            for nm.view_items.iter().advance |vi| { (v.visit_view_item)(vi, (copy e, v)); }
-            for nm.items.iter().advance |ni| { (v.visit_foreign_item)(*ni, (copy e, v)); }
+            for nm.view_items.iter().advance |vi| {
+                (v.visit_view_item)(vi, (e.clone(), v));
+            }
+            for nm.items.iter().advance |ni| {
+                (v.visit_foreign_item)(*ni, (e.clone(), v));
+            }
         }
         item_ty(ref t, ref tps) => {
-            (v.visit_ty)(t, (copy e, v));
+            (v.visit_ty)(t, (e.clone(), v));
             (v.visit_generics)(tps, (e, v));
         }
         item_enum(ref enum_definition, ref tps) => {
-            (v.visit_generics)(tps, (copy e, v));
+            (v.visit_generics)(tps, (e.clone(), v));
             visit_enum_def(
                 enum_definition,
                 tps,
@@ -182,55 +193,57 @@ pub fn visit_item<E: Copy>(i: &item, (e, v): (E, vt<E>)) {
             );
         }
         item_impl(ref tps, ref traits, ref ty, ref methods) => {
-            (v.visit_generics)(tps, (copy e, v));
+            (v.visit_generics)(tps, (e.clone(), v));
             for traits.iter().advance |p| {
-                visit_trait_ref(p, (copy e, v));
+                visit_trait_ref(p, (e.clone(), v));
             }
-            (v.visit_ty)(ty, (copy e, v));
+            (v.visit_ty)(ty, (e.clone(), v));
             for methods.iter().advance |m| {
-                visit_method_helper(*m, (copy e, v))
+                visit_method_helper(*m, (e.clone(), v))
             }
         }
         item_struct(struct_def, ref generics) => {
-            (v.visit_generics)(generics, (copy e, v));
+            (v.visit_generics)(generics, (e.clone(), v));
             (v.visit_struct_def)(struct_def, i.ident, generics, i.id, (e, v));
         }
         item_trait(ref generics, ref traits, ref methods) => {
-            (v.visit_generics)(generics, (copy e, v));
-            for traits.iter().advance |p| { visit_path(&p.path, (copy e, v)); }
+            (v.visit_generics)(generics, (e.clone(), v));
+            for traits.iter().advance |p| {
+                visit_path(&p.path, (e.clone(), v));
+            }
             for methods.iter().advance |m| {
-                (v.visit_trait_method)(m, (copy e, v));
+                (v.visit_trait_method)(m, (e.clone(), v));
             }
         }
         item_mac(ref m) => visit_mac(m, (e, v))
     }
 }
 
-pub fn visit_enum_def<E: Copy>(enum_definition: &ast::enum_def,
+pub fn visit_enum_def<E:Clone>(enum_definition: &ast::enum_def,
                                tps: &Generics,
                                (e, v): (E, vt<E>)) {
     for enum_definition.variants.iter().advance |vr| {
         match vr.node.kind {
             tuple_variant_kind(ref variant_args) => {
                 for variant_args.iter().advance |va| {
-                    (v.visit_ty)(&va.ty, (copy e, v));
+                    (v.visit_ty)(&va.ty, (e.clone(), v));
                 }
             }
             struct_variant_kind(struct_def) => {
                 (v.visit_struct_def)(struct_def, vr.node.name, tps,
-                                     vr.node.id, (copy e, v));
+                                     vr.node.id, (e.clone(), v));
             }
         }
         // Visit the disr expr if it exists
         for vr.node.disr_expr.iter().advance |ex| {
-            (v.visit_expr)(*ex, (copy e, v))
+            (v.visit_expr)(*ex, (e.clone(), v))
         }
     }
 }
 
 pub fn skip_ty<E>(_t: &Ty, (_e,_v): (E, vt<E>)) {}
 
-pub fn visit_ty<E: Copy>(t: &Ty, (e, v): (E, vt<E>)) {
+pub fn visit_ty<E:Clone>(t: &Ty, (e, v): (E, vt<E>)) {
     match t.node {
         ty_box(ref mt) | ty_uniq(ref mt) |
         ty_vec(ref mt) | ty_ptr(ref mt) | ty_rptr(_, ref mt) => {
@@ -238,92 +251,96 @@ pub fn visit_ty<E: Copy>(t: &Ty, (e, v): (E, vt<E>)) {
         },
         ty_tup(ref ts) => {
             for ts.iter().advance |tt| {
-                (v.visit_ty)(tt, (copy e, v));
+                (v.visit_ty)(tt, (e.clone(), v));
             }
         },
         ty_closure(ref f) => {
-            for f.decl.inputs.iter().advance |a| { (v.visit_ty)(&a.ty, (copy e, v)); }
-            (v.visit_ty)(&f.decl.output, (copy e, v));
+            for f.decl.inputs.iter().advance |a| {
+                (v.visit_ty)(&a.ty, (e.clone(), v));
+            }
+            (v.visit_ty)(&f.decl.output, (e.clone(), v));
             do f.bounds.map |bounds| {
-                visit_ty_param_bounds(bounds, (copy e, v));
+                visit_ty_param_bounds(bounds, (e.clone(), v));
             };
         },
         ty_bare_fn(ref f) => {
-            for f.decl.inputs.iter().advance |a| { (v.visit_ty)(&a.ty, (copy e, v)); }
+            for f.decl.inputs.iter().advance |a| {
+                (v.visit_ty)(&a.ty, (e.clone(), v));
+            }
             (v.visit_ty)(&f.decl.output, (e, v));
         },
         ty_path(ref p, ref bounds, _) => {
-            visit_path(p, (copy e, v));
+            visit_path(p, (e.clone(), v));
             do bounds.map |bounds| {
-                visit_ty_param_bounds(bounds, (copy e, v));
+                visit_ty_param_bounds(bounds, (e.clone(), v));
             };
         },
         ty_fixed_length_vec(ref mt, ex) => {
-            (v.visit_ty)(mt.ty, (copy e, v));
-            (v.visit_expr)(ex, (copy e, v));
+            (v.visit_ty)(mt.ty, (e.clone(), v));
+            (v.visit_expr)(ex, (e.clone(), v));
         },
         ty_nil | ty_bot | ty_mac(_) | ty_infer => ()
     }
 }
 
-pub fn visit_path<E: Copy>(p: &Path, (e, v): (E, vt<E>)) {
-    for p.types.iter().advance |tp| { (v.visit_ty)(tp, (copy e, v)); }
+pub fn visit_path<E:Clone>(p: &Path, (e, v): (E, vt<E>)) {
+    for p.types.iter().advance |tp| { (v.visit_ty)(tp, (e.clone(), v)); }
 }
 
-pub fn visit_pat<E: Copy>(p: &pat, (e, v): (E, vt<E>)) {
+pub fn visit_pat<E:Clone>(p: &pat, (e, v): (E, vt<E>)) {
     match p.node {
         pat_enum(ref path, ref children) => {
-            visit_path(path, (copy e, v));
+            visit_path(path, (e.clone(), v));
             for children.iter().advance |children| {
                 for children.iter().advance |child| {
-                    (v.visit_pat)(*child, (copy e, v));
+                    (v.visit_pat)(*child, (e.clone(), v));
                 }
             }
         }
         pat_struct(ref path, ref fields, _) => {
-            visit_path(path, (copy e, v));
+            visit_path(path, (e.clone(), v));
             for fields.iter().advance |f| {
-                (v.visit_pat)(f.pat, (copy e, v));
+                (v.visit_pat)(f.pat, (e.clone(), v));
             }
         }
         pat_tup(ref elts) => {
             for elts.iter().advance |elt| {
-                (v.visit_pat)(*elt, (copy e, v))
+                (v.visit_pat)(*elt, (e.clone(), v))
             }
         },
         pat_box(inner) | pat_uniq(inner) | pat_region(inner) => {
             (v.visit_pat)(inner, (e, v))
         },
         pat_ident(_, ref path, ref inner) => {
-            visit_path(path, (copy e, v));
+            visit_path(path, (e.clone(), v));
             for inner.iter().advance |subpat| {
-                (v.visit_pat)(*subpat, (copy e, v))
+                (v.visit_pat)(*subpat, (e.clone(), v))
             }
         }
         pat_lit(ex) => (v.visit_expr)(ex, (e, v)),
         pat_range(e1, e2) => {
-            (v.visit_expr)(e1, (copy e, v));
+            (v.visit_expr)(e1, (e.clone(), v));
             (v.visit_expr)(e2, (e, v));
         }
         pat_wild => (),
         pat_vec(ref before, ref slice, ref after) => {
             for before.iter().advance |elt| {
-                (v.visit_pat)(*elt, (copy e, v));
+                (v.visit_pat)(*elt, (e.clone(), v));
             }
             for slice.iter().advance |elt| {
-                (v.visit_pat)(*elt, (copy e, v));
+                (v.visit_pat)(*elt, (e.clone(), v));
             }
             for after.iter().advance |tail| {
-                (v.visit_pat)(*tail, (copy e, v));
+                (v.visit_pat)(*tail, (e.clone(), v));
             }
         }
     }
 }
 
-pub fn visit_foreign_item<E: Copy>(ni: &foreign_item, (e, v): (E, vt<E>)) {
+pub fn visit_foreign_item<E:Clone>(ni: &foreign_item, (e, v): (E, vt<E>)) {
     match ni.node {
         foreign_item_fn(ref fd, _, ref generics) => {
-            visit_fn_decl(fd, (copy e, v));
+            visit_fn_decl(fd, (e.clone(), v));
             (v.visit_generics)(generics, (e, v));
         }
         foreign_item_static(ref t, _) => {
@@ -332,26 +349,26 @@ pub fn visit_foreign_item<E: Copy>(ni: &foreign_item, (e, v): (E, vt<E>)) {
     }
 }
 
-pub fn visit_ty_param_bounds<E: Copy>(bounds: &OptVec<TyParamBound>,
+pub fn visit_ty_param_bounds<E:Clone>(bounds: &OptVec<TyParamBound>,
                                       (e, v): (E, vt<E>)) {
     for bounds.iter().advance |bound| {
         match *bound {
-            TraitTyParamBound(ref ty) => visit_trait_ref(ty, (copy e, v)),
+            TraitTyParamBound(ref ty) => visit_trait_ref(ty, (e.clone(), v)),
             RegionTyParamBound => {}
         }
     }
 }
 
-pub fn visit_generics<E: Copy>(generics: &Generics, (e, v): (E, vt<E>)) {
+pub fn visit_generics<E:Clone>(generics: &Generics, (e, v): (E, vt<E>)) {
     for generics.ty_params.iter().advance |tp| {
-        visit_ty_param_bounds(&tp.bounds, (copy e, v));
+        visit_ty_param_bounds(&tp.bounds, (e.clone(), v));
     }
 }
 
-pub fn visit_fn_decl<E: Copy>(fd: &fn_decl, (e, v): (E, vt<E>)) {
+pub fn visit_fn_decl<E:Clone>(fd: &fn_decl, (e, v): (E, vt<E>)) {
     for fd.inputs.iter().advance |a| {
-        (v.visit_pat)(a.pat, (copy e, v));
-        (v.visit_ty)(&a.ty, (copy e, v));
+        (v.visit_pat)(a.pat, (e.clone(), v));
+        (v.visit_ty)(&a.ty, (e.clone(), v));
     }
     (v.visit_ty)(&fd.output, (e, v));
 }
@@ -360,7 +377,7 @@ pub fn visit_fn_decl<E: Copy>(fd: &fn_decl, (e, v): (E, vt<E>)) {
 // visit_fn() and check for fk_method().  I named this visit_method_helper()
 // because it is not a default impl of any method, though I doubt that really
 // clarifies anything. - Niko
-pub fn visit_method_helper<E: Copy>(m: &method, (e, v): (E, vt<E>)) {
+pub fn visit_method_helper<E:Clone>(m: &method, (e, v): (E, vt<E>)) {
     (v.visit_fn)(&fk_method(m.ident, &m.generics, m),
                  &m.decl,
                  &m.body,
@@ -369,28 +386,30 @@ pub fn visit_method_helper<E: Copy>(m: &method, (e, v): (E, vt<E>)) {
                  (e, v));
 }
 
-pub fn visit_fn<E: Copy>(fk: &fn_kind, decl: &fn_decl, body: &blk, _sp: span,
+pub fn visit_fn<E:Clone>(fk: &fn_kind, decl: &fn_decl, body: &blk, _sp: span,
                          _id: node_id, (e, v): (E, vt<E>)) {
-    visit_fn_decl(decl, (copy e, v));
+    visit_fn_decl(decl, (e.clone(), v));
     let generics = generics_of_fn(fk);
-    (v.visit_generics)(&generics, (copy e, v));
+    (v.visit_generics)(&generics, (e.clone(), v));
     (v.visit_block)(body, (e, v));
 }
 
-pub fn visit_ty_method<E: Copy>(m: &ty_method, (e, v): (E, vt<E>)) {
-    for m.decl.inputs.iter().advance |a| { (v.visit_ty)(&a.ty, (copy e, v)); }
-    (v.visit_generics)(&m.generics, (copy e, v));
+pub fn visit_ty_method<E:Clone>(m: &ty_method, (e, v): (E, vt<E>)) {
+    for m.decl.inputs.iter().advance |a| {
+        (v.visit_ty)(&a.ty, (e.clone(), v));
+    }
+    (v.visit_generics)(&m.generics, (e.clone(), v));
     (v.visit_ty)(&m.decl.output, (e, v));
 }
 
-pub fn visit_trait_method<E: Copy>(m: &trait_method, (e, v): (E, vt<E>)) {
+pub fn visit_trait_method<E:Clone>(m: &trait_method, (e, v): (E, vt<E>)) {
     match *m {
       required(ref ty_m) => (v.visit_ty_method)(ty_m, (e, v)),
       provided(m) => visit_method_helper(m, (e, v))
     }
 }
 
-pub fn visit_struct_def<E: Copy>(
+pub fn visit_struct_def<E:Clone>(
     sd: @struct_def,
     _nm: ast::ident,
     _generics: &Generics,
@@ -398,20 +417,20 @@ pub fn visit_struct_def<E: Copy>(
     (e, v): (E, vt<E>)
 ) {
     for sd.fields.iter().advance |f| {
-        (v.visit_struct_field)(*f, (copy e, v));
+        (v.visit_struct_field)(*f, (e.clone(), v));
     }
 }
 
-pub fn visit_struct_field<E: Copy>(sf: &struct_field, (e, v): (E, vt<E>)) {
+pub fn visit_struct_field<E:Clone>(sf: &struct_field, (e, v): (E, vt<E>)) {
     (v.visit_ty)(&sf.node.ty, (e, v));
 }
 
-pub fn visit_block<E: Copy>(b: &blk, (e, v): (E, vt<E>)) {
+pub fn visit_block<E:Clone>(b: &blk, (e, v): (E, vt<E>)) {
     for b.view_items.iter().advance |vi| {
-        (v.visit_view_item)(vi, (copy e, v));
+        (v.visit_view_item)(vi, (e.clone(), v));
     }
     for b.stmts.iter().advance |s| {
-        (v.visit_stmt)(*s, (copy e, v));
+        (v.visit_stmt)(*s, (e.clone(), v));
     }
     visit_expr_opt(b.expr, (e, v));
 }
@@ -425,7 +444,7 @@ pub fn visit_stmt<E>(s: &stmt, (e, v): (E, vt<E>)) {
     }
 }
 
-pub fn visit_decl<E: Copy>(d: &decl, (e, v): (E, vt<E>)) {
+pub fn visit_decl<E:Clone>(d: &decl, (e, v): (E, vt<E>)) {
     match d.node {
         decl_local(ref loc) => (v.visit_local)(*loc, (e, v)),
         decl_item(it) => (v.visit_item)(it, (e, v))
@@ -436,67 +455,67 @@ pub fn visit_expr_opt<E>(eo: Option<@expr>, (e, v): (E, vt<E>)) {
     match eo { None => (), Some(ex) => (v.visit_expr)(ex, (e, v)) }
 }
 
-pub fn visit_exprs<E: Copy>(exprs: &[@expr], (e, v): (E, vt<E>)) {
-    for exprs.iter().advance |ex| { (v.visit_expr)(*ex, (copy e, v)); }
+pub fn visit_exprs<E:Clone>(exprs: &[@expr], (e, v): (E, vt<E>)) {
+    for exprs.iter().advance |ex| { (v.visit_expr)(*ex, (e.clone(), v)); }
 }
 
 pub fn visit_mac<E>(_m: &mac, (_e, _v): (E, vt<E>)) {
     /* no user-serviceable parts inside */
 }
 
-pub fn visit_expr<E: Copy>(ex: @expr, (e, v): (E, vt<E>)) {
+pub fn visit_expr<E:Clone>(ex: @expr, (e, v): (E, vt<E>)) {
     match ex.node {
-        expr_vstore(x, _) => (v.visit_expr)(x, (copy e, v)),
-        expr_vec(ref es, _) => visit_exprs(*es, (copy e, v)),
+        expr_vstore(x, _) => (v.visit_expr)(x, (e.clone(), v)),
+        expr_vec(ref es, _) => visit_exprs(*es, (e.clone(), v)),
         expr_repeat(element, count, _) => {
-            (v.visit_expr)(element, (copy e, v));
-            (v.visit_expr)(count, (copy e, v));
+            (v.visit_expr)(element, (e.clone(), v));
+            (v.visit_expr)(count, (e.clone(), v));
         }
         expr_struct(ref p, ref flds, base) => {
-            visit_path(p, (copy e, v));
+            visit_path(p, (e.clone(), v));
             for flds.iter().advance |f| {
-                (v.visit_expr)(f.node.expr, (copy e, v));
+                (v.visit_expr)(f.node.expr, (e.clone(), v));
             }
-            visit_expr_opt(base, (copy e, v));
+            visit_expr_opt(base, (e.clone(), v));
         }
         expr_tup(ref elts) => {
-            for elts.iter().advance |el| { (v.visit_expr)(*el, (copy e, v)) }
+            for elts.iter().advance |el| { (v.visit_expr)(*el, (e.clone(), v)) }
         }
         expr_call(callee, ref args, _) => {
-            visit_exprs(*args, (copy e, v));
-            (v.visit_expr)(callee, (copy e, v));
+            visit_exprs(*args, (e.clone(), v));
+            (v.visit_expr)(callee, (e.clone(), v));
         }
         expr_method_call(_, callee, _, ref tys, ref args, _) => {
-            visit_exprs(*args, (copy e, v));
+            visit_exprs(*args, (e.clone(), v));
             for tys.iter().advance |tp| {
-                (v.visit_ty)(tp, (copy e, v));
+                (v.visit_ty)(tp, (e.clone(), v));
             }
-            (v.visit_expr)(callee, (copy e, v));
+            (v.visit_expr)(callee, (e.clone(), v));
         }
         expr_binary(_, _, a, b) => {
-            (v.visit_expr)(a, (copy e, v));
-            (v.visit_expr)(b, (copy e, v));
+            (v.visit_expr)(a, (e.clone(), v));
+            (v.visit_expr)(b, (e.clone(), v));
         }
         expr_addr_of(_, x) | expr_unary(_, _, x) |
-        expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, (copy e, v)),
+        expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, (e.clone(), v)),
         expr_lit(_) => (),
         expr_cast(x, ref t) => {
-            (v.visit_expr)(x, (copy e, v));
-            (v.visit_ty)(t, (copy e, v));
+            (v.visit_expr)(x, (e.clone(), v));
+            (v.visit_ty)(t, (e.clone(), v));
         }
         expr_if(x, ref b, eo) => {
-            (v.visit_expr)(x, (copy e, v));
-            (v.visit_block)(b, (copy e, v));
-            visit_expr_opt(eo, (copy e, v));
+            (v.visit_expr)(x, (e.clone(), v));
+            (v.visit_block)(b, (e.clone(), v));
+            visit_expr_opt(eo, (e.clone(), v));
         }
         expr_while(x, ref b) => {
-            (v.visit_expr)(x, (copy e, v));
-            (v.visit_block)(b, (copy e, v));
+            (v.visit_expr)(x, (e.clone(), v));
+            (v.visit_block)(b, (e.clone(), v));
         }
-        expr_loop(ref b, _) => (v.visit_block)(b, (copy e, v)),
+        expr_loop(ref b, _) => (v.visit_block)(b, (e.clone(), v)),
         expr_match(x, ref arms) => {
-            (v.visit_expr)(x, (copy e, v));
-            for arms.iter().advance |a| { (v.visit_arm)(a, (copy e, v)); }
+            (v.visit_expr)(x, (e.clone(), v));
+            for arms.iter().advance |a| { (v.visit_arm)(a, (e.clone(), v)); }
         }
         expr_fn_block(ref decl, ref body) => {
             (v.visit_fn)(
@@ -505,56 +524,56 @@ pub fn visit_expr<E: Copy>(ex: @expr, (e, v): (E, vt<E>)) {
                 body,
                 ex.span,
                 ex.id,
-                (copy e, v)
+                (e.clone(), v)
             );
         }
-        expr_block(ref b) => (v.visit_block)(b, (copy e, v)),
+        expr_block(ref b) => (v.visit_block)(b, (e.clone(), v)),
         expr_assign(a, b) => {
-            (v.visit_expr)(b, (copy e, v));
-            (v.visit_expr)(a, (copy e, v));
+            (v.visit_expr)(b, (e.clone(), v));
+            (v.visit_expr)(a, (e.clone(), v));
         }
-        expr_copy(a) => (v.visit_expr)(a, (copy e, v)),
+        expr_copy(a) => (v.visit_expr)(a, (e.clone(), v)),
         expr_assign_op(_, _, a, b) => {
-            (v.visit_expr)(b, (copy e, v));
-            (v.visit_expr)(a, (copy e, v));
+            (v.visit_expr)(b, (e.clone(), v));
+            (v.visit_expr)(a, (e.clone(), v));
         }
         expr_field(x, _, ref tys) => {
-            (v.visit_expr)(x, (copy e, v));
+            (v.visit_expr)(x, (e.clone(), v));
             for tys.iter().advance |tp| {
-                (v.visit_ty)(tp, (copy e, v));
+                (v.visit_ty)(tp, (e.clone(), v));
             }
         }
         expr_index(_, a, b) => {
-            (v.visit_expr)(a, (copy e, v));
-            (v.visit_expr)(b, (copy e, v));
+            (v.visit_expr)(a, (e.clone(), v));
+            (v.visit_expr)(b, (e.clone(), v));
         }
-        expr_path(ref p) => visit_path(p, (copy e, v)),
+        expr_path(ref p) => visit_path(p, (e.clone(), v)),
         expr_self => (),
         expr_break(_) => (),
         expr_again(_) => (),
-        expr_ret(eo) => visit_expr_opt(eo, (copy e, v)),
+        expr_ret(eo) => visit_expr_opt(eo, (e.clone(), v)),
         expr_log(lv, x) => {
-            (v.visit_expr)(lv, (copy e, v));
-            (v.visit_expr)(x, (copy e, v));
+            (v.visit_expr)(lv, (e.clone(), v));
+            (v.visit_expr)(x, (e.clone(), v));
         }
-        expr_mac(ref mac) => visit_mac(mac, (copy e, v)),
-        expr_paren(x) => (v.visit_expr)(x, (copy e, v)),
+        expr_mac(ref mac) => visit_mac(mac, (e.clone(), v)),
+        expr_paren(x) => (v.visit_expr)(x, (e.clone(), v)),
         expr_inline_asm(ref a) => {
             for a.inputs.iter().advance |&(_, in)| {
-                (v.visit_expr)(in, (copy e, v));
+                (v.visit_expr)(in, (e.clone(), v));
             }
             for a.outputs.iter().advance |&(_, out)| {
-                (v.visit_expr)(out, (copy e, v));
+                (v.visit_expr)(out, (e.clone(), v));
             }
         }
     }
     (v.visit_expr_post)(ex, (e, v));
 }
 
-pub fn visit_arm<E: Copy>(a: &arm, (e, v): (E, vt<E>)) {
-    for a.pats.iter().advance |p| { (v.visit_pat)(*p, (copy e, v)); }
-    visit_expr_opt(a.guard, (copy e, v));
-    (v.visit_block)(&a.body, (copy e, v));
+pub fn visit_arm<E:Clone>(a: &arm, (e, v): (E, vt<E>)) {
+    for a.pats.iter().advance |p| { (v.visit_pat)(*p, (e.clone(), v)); }
+    visit_expr_opt(a.guard, (e.clone(), v));
+    (v.visit_block)(&a.body, (e.clone(), v));
 }
 
 // Simpler, non-context passing interface. Always walks the whole tree, simply
diff --git a/src/test/auxiliary/cci_capture_clause.rs b/src/test/auxiliary/cci_capture_clause.rs
index beca0adbe3c..61a3ca1559c 100644
--- a/src/test/auxiliary/cci_capture_clause.rs
+++ b/src/test/auxiliary/cci_capture_clause.rs
@@ -11,10 +11,10 @@
 use std::comm::*;
 use std::task;
 
-pub fn foo<T:Send + Copy>(x: T) -> Port<T> {
+pub fn foo<T:Send + Clone>(x: T) -> Port<T> {
     let (p, c) = stream();
     do task::spawn() {
-        c.send(copy x);
+        c.send(x.clone());
     }
     p
 }
diff --git a/src/test/auxiliary/cci_class_cast.rs b/src/test/auxiliary/cci_class_cast.rs
index 1e82b85f728..c1e23f1f5c8 100644
--- a/src/test/auxiliary/cci_class_cast.rs
+++ b/src/test/auxiliary/cci_class_cast.rs
@@ -18,7 +18,7 @@ pub mod kitty {
     }
 
     impl ToStr for cat {
-       fn to_str(&self) -> ~str { copy self.name }
+       fn to_str(&self) -> ~str { self.name.clone() }
     }
 
     impl cat {
diff --git a/src/test/auxiliary/cci_nested_lib.rs b/src/test/auxiliary/cci_nested_lib.rs
index 2c9b28e6282..d53b7d825cb 100644
--- a/src/test/auxiliary/cci_nested_lib.rs
+++ b/src/test/auxiliary/cci_nested_lib.rs
@@ -18,26 +18,28 @@ pub struct alist<A,B> {
     data: @mut ~[Entry<A,B>]
 }
 
-pub fn alist_add<A:Copy,B:Copy>(lst: &alist<A,B>, k: A, v: B) {
+pub fn alist_add<A,B>(lst: &alist<A,B>, k: A, v: B) {
     lst.data.push(Entry{key:k, value:v});
 }
 
-pub fn alist_get<A:Copy,B:Copy>(lst: &alist<A,B>, k: A) -> B {
+pub fn alist_get<A:Clone,B:Clone>(lst: &alist<A,B>, k: A) -> B {
     let eq_fn = lst.eq_fn;
     for lst.data.iter().advance |entry| {
-        if eq_fn(copy entry.key, copy k) { return copy entry.value; }
+        if eq_fn(entry.key.clone(), k.clone()) {
+            return entry.value.clone();
+        }
     }
     fail!();
 }
 
 #[inline]
-pub fn new_int_alist<B:Copy>() -> alist<int, B> {
+pub fn new_int_alist<B>() -> alist<int, B> {
     fn eq_int(a: int, b: int) -> bool { a == b }
     return alist {eq_fn: eq_int, data: @mut ~[]};
 }
 
 #[inline]
-pub fn new_int_alist_2<B:Copy>() -> alist<int, B> {
+pub fn new_int_alist_2<B>() -> alist<int, B> {
     #[inline]
     fn eq_int(a: int, b: int) -> bool { a == b }
     return alist {eq_fn: eq_int, data: @mut ~[]};
diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs
index 8afc0327755..75a4b6e2621 100644
--- a/src/test/auxiliary/issue-2631-a.rs
+++ b/src/test/auxiliary/issue-2631-a.rs
@@ -18,6 +18,6 @@ use std::hashmap::HashMap;
 pub type header_map = HashMap<~str, @mut ~[@~str]>;
 
 // the unused ty param is necessary so this gets monomorphized
-pub fn request<T:Copy>(req: &header_map) {
-  let _x = copy *(copy **req.get(&~"METHOD"))[0u];
+pub fn request<T>(req: &header_map) {
+  let _x = (*((**req.get(&~"METHOD")).clone())[0u]).clone();
 }
diff --git a/src/test/auxiliary/issue2378a.rs b/src/test/auxiliary/issue2378a.rs
index 1873aca5909..eed271c5499 100644
--- a/src/test/auxiliary/issue2378a.rs
+++ b/src/test/auxiliary/issue2378a.rs
@@ -13,10 +13,10 @@
 
 enum maybe<T> { just(T), nothing }
 
-impl <T:Copy> Index<uint,T> for maybe<T> {
+impl <T:Clone> Index<uint,T> for maybe<T> {
     fn index(&self, idx: &uint) -> T {
         match self {
-            &just(ref t) => copy *t,
+            &just(ref t) => (*t).clone(),
             &nothing => { fail!(); }
         }
     }
diff --git a/src/test/auxiliary/issue2378b.rs b/src/test/auxiliary/issue2378b.rs
index 20f07a5cb54..d2c42bacc63 100644
--- a/src/test/auxiliary/issue2378b.rs
+++ b/src/test/auxiliary/issue2378b.rs
@@ -17,7 +17,7 @@ use issue2378a::maybe;
 
 struct two_maybes<T> {a: maybe<T>, b: maybe<T>}
 
-impl <T:Copy> Index<uint,(T,T)> for two_maybes<T> {
+impl<T:Clone> Index<uint,(T,T)> for two_maybes<T> {
     fn index(&self, idx: &uint) -> (T, T) {
         (self.a[*idx], self.b[*idx])
     }
diff --git a/src/test/auxiliary/issue4516_ty_param_lib.rs b/src/test/auxiliary/issue4516_ty_param_lib.rs
index 391e9b39610..cd90c9b06c4 100644
--- a/src/test/auxiliary/issue4516_ty_param_lib.rs
+++ b/src/test/auxiliary/issue4516_ty_param_lib.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub fn to_closure<A:'static + Copy>(x: A) -> @fn() -> A {
-    let result: @fn() -> A = || copy x;
+pub fn to_closure<A:'static + Clone>(x: A) -> @fn() -> A {
+    let result: @fn() -> A = || x.clone();
     result
 }
diff --git a/src/test/auxiliary/issue_2242_a.rs b/src/test/auxiliary/issue_2242_a.rs
index c2caf1e77ee..9f504db8f2a 100644
--- a/src/test/auxiliary/issue_2242_a.rs
+++ b/src/test/auxiliary/issue_2242_a.rs
@@ -16,5 +16,5 @@ trait to_strz {
 }
 
 impl to_strz for ~str {
-    fn to_strz() -> ~str { copy self }
+    fn to_strz() -> ~str { self.clone() }
 }
diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs
index f0ffa3237b5..bbdfd3ecf79 100644
--- a/src/test/bench/graph500-bfs.rs
+++ b/src/test/bench/graph500-bfs.rs
@@ -198,7 +198,11 @@ fn bfs2(graph: graph, key: node_id) -> bfs_result {
               white => {
                 let i = i as node_id;
 
+<<<<<<< HEAD
                 let neighbors = &graph[i];
+=======
+                let neighbors = graph[i].clone();
+>>>>>>> librustc: Remove all uses of "copy".
 
                 let mut color = white;
 
@@ -283,7 +287,7 @@ fn pbfs(graph: &arc::ARC<graph>, key: node_id) -> bfs_result {
                   white => {
                     let i = i as node_id;
 
-                    let neighbors = copy graph[i];
+                    let neighbors = graph[i].clone();
 
                     let mut color = white;
 
@@ -397,7 +401,7 @@ fn validate(edges: ~[(node_id, node_id)],
     info!(~"Verifying tree and graph edges...");
 
     let status = do par::alli(tree) {
-        let edges = copy edges;
+        let edges = edges.clone();
         let result: ~fn(x: uint, v: &i64) -> bool = |u, v| {
             let u = u as node_id;
             if *v == -1i64 || u == root {
@@ -438,7 +442,7 @@ fn main() {
                                  edges.len(), stop - start));
 
     let start = time::precise_time_s();
-    let graph = make_graph(1 << scale, copy edges);
+    let graph = make_graph(1 << scale, edges.clone());
     let stop = time::precise_time_s();
 
     let mut total_edges = 0;
@@ -451,7 +455,7 @@ fn main() {
     let mut total_seq = 0.0;
     let mut total_par = 0.0;
 
-    let graph_arc = arc::ARC(copy graph);
+    let graph_arc = arc::ARC(graph.clone());
 
     do gen_search_keys(graph, num_keys).map() |root| {
         io::stdout().write_line(~"");
@@ -459,7 +463,7 @@ fn main() {
 
         if do_sequential {
             let start = time::precise_time_s();
-            let bfs_tree = bfs(copy graph, *root);
+            let bfs_tree = bfs(graph.clone(), *root);
             let stop = time::precise_time_s();
 
             //total_seq += stop - start;
@@ -470,7 +474,7 @@ fn main() {
 
             if do_validate {
                 let start = time::precise_time_s();
-                assert!((validate(copy edges, *root, bfs_tree)));
+                assert!((validate(edges.clone(), *root, bfs_tree)));
                 let stop = time::precise_time_s();
 
                 io::stdout().write_line(
@@ -479,7 +483,7 @@ fn main() {
             }
 
             let start = time::precise_time_s();
-            let bfs_tree = bfs2(copy graph, *root);
+            let bfs_tree = bfs2(graph.clone(), *root);
             let stop = time::precise_time_s();
 
             total_seq += stop - start;
@@ -490,7 +494,7 @@ fn main() {
 
             if do_validate {
                 let start = time::precise_time_s();
-                assert!((validate(copy edges, *root, bfs_tree)));
+                assert!((validate(edges.clone(), *root, bfs_tree)));
                 let stop = time::precise_time_s();
 
                 io::stdout().write_line(
@@ -510,7 +514,7 @@ fn main() {
 
         if do_validate {
             let start = time::precise_time_s();
-            assert!((validate(copy edges, *root, bfs_tree)));
+            assert!((validate(edges.clone(), *root, bfs_tree)));
             let stop = time::precise_time_s();
 
             io::stdout().write_line(fmt!("Validation completed in %? seconds.",
diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs
index 91576bad73d..8aff30ec80a 100644
--- a/src/test/bench/msgsend-pipes-shared.rs
+++ b/src/test/bench/msgsend-pipes-shared.rs
@@ -43,7 +43,7 @@ fn server(requests: &Port<request>, responses: &comm::Chan<uint>) {
     let mut done = false;
     while !done {
         match requests.try_recv() {
-          Some(get_count) => { responses.send(copy count); }
+          Some(get_count) => { responses.send(count.clone()); }
           Some(bytes(b)) => {
             //error!("server: received %? bytes", b);
             count += b;
@@ -107,7 +107,7 @@ fn main() {
     } else if args.len() <= 1u {
         ~[~"", ~"10000", ~"4"]
     } else {
-        copy args
+        args.clone()
     };
 
     info!("%?", args);
diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs
index 12c0871566c..0046fb9dd12 100644
--- a/src/test/bench/msgsend-pipes.rs
+++ b/src/test/bench/msgsend-pipes.rs
@@ -34,11 +34,11 @@ enum request {
 }
 
 fn server(requests: &PortSet<request>, responses: &Chan<uint>) {
-    let mut count = 0;
+    let mut count: uint = 0;
     let mut done = false;
     while !done {
         match requests.try_recv() {
-          Some(get_count) => { responses.send(copy count); }
+          Some(get_count) => { responses.send(count.clone()); }
           Some(bytes(b)) => {
             //error!("server: received %? bytes", b);
             count += b;
@@ -103,7 +103,7 @@ fn main() {
     } else if args.len() <= 1u {
         ~[~"", ~"10000", ~"4"]
     } else {
-        copy args
+        args.clone()
     };
 
     info!("%?", args);
diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs
index 0bf492ae55f..a60e0b9e340 100644
--- a/src/test/bench/msgsend-ring-mutex-arcs.rs
+++ b/src/test/bench/msgsend-ring-mutex-arcs.rs
@@ -77,7 +77,7 @@ fn main() {
     } else if args.len() <= 1u {
         ~[~"", ~"10", ~"100"]
     } else {
-        copy args
+        args.clone()
     };
 
     let num_tasks = uint::from_str(args[1]).get();
diff --git a/src/test/bench/msgsend-ring-pipes.rs b/src/test/bench/msgsend-ring-pipes.rs
index 0f6ca37a3fb..b4692c774aa 100644
--- a/src/test/bench/msgsend-ring-pipes.rs
+++ b/src/test/bench/msgsend-ring-pipes.rs
@@ -63,7 +63,7 @@ fn main() {
     } else if args.len() <= 1u {
         ~[~"", ~"100", ~"1000"]
     } else {
-        copy args
+        args.clone()
     };
 
     let num_tasks = uint::from_str(args[1]).get();
diff --git a/src/test/bench/msgsend-ring-rw-arcs.rs b/src/test/bench/msgsend-ring-rw-arcs.rs
index a5f96b35999..0c6b97c6b78 100644
--- a/src/test/bench/msgsend-ring-rw-arcs.rs
+++ b/src/test/bench/msgsend-ring-rw-arcs.rs
@@ -73,7 +73,7 @@ fn main() {
     } else if args.len() <= 1u {
         ~[~"", ~"10", ~"100"]
     } else {
-        copy args
+        args.clone()
     };
 
     let num_tasks = uint::from_str(args[1]).get();
diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs
index da8d65a1dcb..f6e90d1b745 100644
--- a/src/test/bench/shootout-fasta.rs
+++ b/src/test/bench/shootout-fasta.rs
@@ -37,6 +37,7 @@ fn myrandom_next(r: @mut MyRandom, mx: u32) -> u32 {
     mx * r.last / 139968u32
 }
 
+#[deriving(Clone)]
 struct AminoAcids {
     ch: char,
     prob: u32
@@ -59,10 +60,14 @@ fn select_random(r: u32, genelist: ~[AminoAcids]) -> char {
             let mid: uint = lo + (hi - lo) / 2u;
             if target < v[mid].prob {
                 return bisect(v, lo, mid, target);
-            } else { return bisect(v, mid, hi, target); }
-        } else { return v[hi].ch; }
+            } else {
+                return bisect(v, mid, hi, target);
+            }
+        } else {
+            return v[hi].ch;
+        }
     }
-    bisect(copy genelist, 0, genelist.len() - 1, r)
+    bisect(genelist.clone(), 0, genelist.len() - 1, r)
 }
 
 fn make_random_fasta(wr: @io::Writer,
@@ -78,7 +83,7 @@ fn make_random_fasta(wr: @io::Writer,
     let mut op: ~str = ~"";
     for uint::range(0u, n as uint) |_i| {
         op.push_char(select_random(myrandom_next(rng, 100u32),
-                                              copy genelist));
+                                   genelist.clone()));
         if op.len() >= LINE_LENGTH {
             wr.write_line(op);
             op = ~"";
diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs
index 919c4daeb25..64cfa2561a4 100644
--- a/src/test/bench/shootout-k-nucleotide-pipes.rs
+++ b/src/test/bench/shootout-k-nucleotide-pipes.rs
@@ -34,22 +34,31 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str {
       return (xx as float) * 100f / (yy as float);
    }
 
-   fn le_by_val<TT:Copy,UU:Copy + Ord>(kv0: &(TT,UU),
-                                         kv1: &(TT,UU)) -> bool {
-      let (_, v0) = copy *kv0;
-      let (_, v1) = copy *kv1;
+   fn le_by_val<TT:Copy + Clone,
+                UU:Copy + Clone + Ord>(
+                kv0: &(TT,UU),
+                kv1: &(TT,UU))
+                -> bool {
+      let (_, v0) = (*kv0).clone();
+      let (_, v1) = (*kv1).clone();
       return v0 >= v1;
    }
 
-   fn le_by_key<TT:Copy + Ord,UU:Copy>(kv0: &(TT,UU),
-                                         kv1: &(TT,UU)) -> bool {
-      let (k0, _) = copy *kv0;
-      let (k1, _) = copy *kv1;
+   fn le_by_key<TT:Copy + Clone + Ord,
+                UU:Copy + Clone>(
+                kv0: &(TT,UU),
+                kv1: &(TT,UU))
+                -> bool {
+      let (k0, _) = (*kv0).clone();
+      let (k1, _) = (*kv1).clone();
       return k0 <= k1;
    }
 
    // sort by key, then by value
-   fn sortKV<TT:Copy + Ord,UU:Copy + Ord>(orig: ~[(TT,UU)]) -> ~[(TT,UU)] {
+   fn sortKV<TT:Copy + Clone + Ord,
+             UU:Copy + Clone + Ord>(
+             orig: ~[(TT,UU)])
+             -> ~[(TT,UU)] {
       return sort::merge_sort(sort::merge_sort(orig, le_by_key), le_by_val);
    }
 
@@ -65,7 +74,7 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str {
    let mut buffer = ~"";
 
    for pairs_sorted.iter().advance |kv| {
-       let (k,v) = copy *kv;
+       let (k,v) = (*kv).clone();
        unsafe {
            let b = str::raw::from_bytes(k);
            // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs
index 295211e03a1..cbc2d3f0ea8 100644
--- a/src/test/bench/shootout-pfib.rs
+++ b/src/test/bench/shootout-pfib.rs
@@ -105,7 +105,7 @@ fn main() {
         args
     };
 
-    let opts = parse_opts(copy args);
+    let opts = parse_opts(args.clone());
 
     if opts.stress {
         stress(2);
diff --git a/src/test/bench/task-perf-jargon-metal-smoke.rs b/src/test/bench/task-perf-jargon-metal-smoke.rs
index e5732b7d580..d3fd20a0293 100644
--- a/src/test/bench/task-perf-jargon-metal-smoke.rs
+++ b/src/test/bench/task-perf-jargon-metal-smoke.rs
@@ -48,7 +48,7 @@ fn main() {
     } else if args.len() <= 1 {
         ~[~"", ~"100"]
     } else {
-        copy args
+        args.clone()
     };
 
     let (p,c) = comm::stream();
diff --git a/src/test/bench/task-perf-linked-failure.rs b/src/test/bench/task-perf-linked-failure.rs
index 514b85c6ae0..e07e5334712 100644
--- a/src/test/bench/task-perf-linked-failure.rs
+++ b/src/test/bench/task-perf-linked-failure.rs
@@ -68,7 +68,7 @@ fn main() {
     } else if args.len() <= 1u {
         ~[~"", ~"100"]
     } else {
-        copy args
+        args.clone()
     };
 
     let num_tasks = uint::from_str(args[1]).get();
diff --git a/src/test/compile-fail/borrowck-lend-flow-match.rs b/src/test/compile-fail/borrowck-lend-flow-match.rs
index fcb31b7b7e0..d5c5597e57f 100644
--- a/src/test/compile-fail/borrowck-lend-flow-match.rs
+++ b/src/test/compile-fail/borrowck-lend-flow-match.rs
@@ -30,7 +30,7 @@ fn separate_arms() {
             x = Some(1); //~ ERROR cannot assign
         }
     }
-    copy x; // just to prevent liveness warnings
+    x.clone(); // just to prevent liveness warnings
 }
 
 fn guard() {
diff --git a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
index 0b9897f23fc..39a0e585ad2 100644
--- a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
+++ b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
@@ -1,5 +1,6 @@
 // Test that we do not permit moves from &[] matched by a vec pattern.
 
+#[deriving(Clone)]
 struct Foo {
     string: ~str
 }
@@ -21,7 +22,7 @@ pub fn main() {
                     ::std::util::unreachable();
                 }
             }
-            let z = copy tail[0];
+            let z = tail[0].clone();
             info!(fmt!("%?", z));
         }
         _ => {
diff --git a/src/test/compile-fail/borrowck-pat-reassign-binding.rs b/src/test/compile-fail/borrowck-pat-reassign-binding.rs
index be2aee5d1b8..8d9718ca380 100644
--- a/src/test/compile-fail/borrowck-pat-reassign-binding.rs
+++ b/src/test/compile-fail/borrowck-pat-reassign-binding.rs
@@ -22,5 +22,5 @@ fn main() {
           x = Some(*i+1); //~ ERROR cannot assign to `x`
       }
     }
-    copy x; // just to prevent liveness warnings
+    x.clone(); // just to prevent liveness warnings
 }
diff --git a/src/test/compile-fail/by-move-pattern-binding.rs b/src/test/compile-fail/by-move-pattern-binding.rs
index 8c0cf68c164..460e2ce23fc 100644
--- a/src/test/compile-fail/by-move-pattern-binding.rs
+++ b/src/test/compile-fail/by-move-pattern-binding.rs
@@ -13,7 +13,7 @@ fn main() {
     let s = S { x: Bar(~"hello") };
     match &s.x {
         &Foo => {}
-        &Bar(identifier) => f(copy identifier)  //~ ERROR cannot move
+        &Bar(identifier) => f(identifier.clone())  //~ ERROR cannot move
     };
     match &s.x {
         &Foo => {}
diff --git a/src/test/compile-fail/copy-a-resource.rs b/src/test/compile-fail/copy-a-resource.rs
index f709ddc0e0d..a90b04b79ad 100644
--- a/src/test/compile-fail/copy-a-resource.rs
+++ b/src/test/compile-fail/copy-a-resource.rs
@@ -24,7 +24,7 @@ fn foo(i:int) -> foo {
 
 fn main() {
     let x = foo(10);
-    let _y = copy x;
-    //~^ ERROR copying a value of non-copyable type `foo`
+    let _y = x.clone();
+    //~^ ERROR does not implement any method in scope
     error!(x);
 }
diff --git a/src/test/compile-fail/infinite-instantiation.rs b/src/test/compile-fail/infinite-instantiation.rs
index 377b2016bcb..1a7cc5d3ad5 100644
--- a/src/test/compile-fail/infinite-instantiation.rs
+++ b/src/test/compile-fail/infinite-instantiation.rs
@@ -21,13 +21,13 @@ impl to_opt for uint {
     }
 }
 
-impl<T:Copy> to_opt for Option<T> {
+impl<T:Clone> to_opt for Option<T> {
     fn to_option(&self) -> Option<Option<T>> {
-        Some(copy *self)
+        Some((*self).clone())
     }
 }
 
-fn function<T:to_opt>(counter: uint, t: T) {
+fn function<T:to_opt + Clone>(counter: uint, t: T) {
     if counter > 0u {
         function(counter - 1u, t.to_option());
     }
diff --git a/src/test/compile-fail/issue-2823.rs b/src/test/compile-fail/issue-2823.rs
index 7d1f64b9dd2..95cb5c6475c 100644
--- a/src/test/compile-fail/issue-2823.rs
+++ b/src/test/compile-fail/issue-2823.rs
@@ -20,6 +20,6 @@ impl Drop for C {
 
 fn main() {
     let c = C{ x: 2};
-    let d = copy c; //~ ERROR copying a value of non-copyable type `C`
+    let d = c.clone(); //~ ERROR does not implement any method in scope
     error!("%?", d.x);
 }
diff --git a/src/test/compile-fail/issue-4542.rs b/src/test/compile-fail/issue-4542.rs
index 6f41e516461..93f55d55e46 100644
--- a/src/test/compile-fail/issue-4542.rs
+++ b/src/test/compile-fail/issue-4542.rs
@@ -12,7 +12,7 @@
 
 fn main() {
     for os::args().each |arg| {
-        match copy *arg {
+        match (*arg).clone() {
             s => { }
         }
     }
diff --git a/src/test/compile-fail/kindck-owned.rs b/src/test/compile-fail/kindck-owned.rs
index 848fd95a560..ed21df4a691 100644
--- a/src/test/compile-fail/kindck-owned.rs
+++ b/src/test/compile-fail/kindck-owned.rs
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn copy1<T:Copy>(t: T) -> @fn() -> T {
-    let result: @fn() -> T = || copy t; //~ ERROR does not fulfill `'static`
+fn copy1<T:Clone>(t: T) -> @fn() -> T {
+    let result: @fn() -> T = || t.clone();  //~ ERROR does not fulfill `'static`
     result
 }
 
-fn copy2<T:Copy + 'static>(t: T) -> @fn() -> T {
-    let result: @fn() -> T = || copy t;
+fn copy2<T:Clone + 'static>(t: T) -> @fn() -> T {
+    let result: @fn() -> T = || t.clone();
     result
 }
 
@@ -24,6 +24,7 @@ fn main() {
 
     copy2(@3);
     copy2(@&x); //~ ERROR does not fulfill `'static`
+<<<<<<< HEAD
 
     let boxed: @fn() = || {};
     copy2(boxed);
@@ -31,4 +32,6 @@ fn main() {
     copy2(owned);    //~ ERROR does not fulfill `Copy`
     let borrowed: &fn:Copy() = || {};
     copy2(borrowed); //~ ERROR does not fulfill `'static`
+=======
+>>>>>>> librustc: Remove all uses of "copy".
 }
diff --git a/src/test/compile-fail/liveness-assign-imm-local-in-loop.rs b/src/test/compile-fail/liveness-assign-imm-local-in-loop.rs
index b74ca055e00..f8afc10c49b 100644
--- a/src/test/compile-fail/liveness-assign-imm-local-in-loop.rs
+++ b/src/test/compile-fail/liveness-assign-imm-local-in-loop.rs
@@ -13,7 +13,7 @@ fn test() {
     loop {
         v = 1; //~ ERROR re-assignment of immutable variable
         //~^ NOTE prior assignment occurs here
-        copy v; // just to prevent liveness warnings
+        v.clone(); // just to prevent liveness warnings
     }
 }
 
diff --git a/src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs b/src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs
index dd134976164..43d7ca83753 100644
--- a/src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs
+++ b/src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs
@@ -12,7 +12,7 @@ fn test() {
     let v: int;
     v = 2;  //~ NOTE prior assignment occurs here
     v += 1; //~ ERROR re-assignment of immutable variable
-    copy v;
+    v.clone();
 }
 
 fn main() {
diff --git a/src/test/compile-fail/liveness-assign-imm-local-with-init.rs b/src/test/compile-fail/liveness-assign-imm-local-with-init.rs
index c830c2d0175..8eb84525b83 100644
--- a/src/test/compile-fail/liveness-assign-imm-local-with-init.rs
+++ b/src/test/compile-fail/liveness-assign-imm-local-with-init.rs
@@ -10,9 +10,9 @@
 
 fn test() {
     let v: int = 1; //~ NOTE prior assignment occurs here
-    copy v;
+    v.clone();
     v = 2; //~ ERROR re-assignment of immutable variable
-    copy v;
+    v.clone();
 }
 
 fn main() {
diff --git a/src/test/compile-fail/liveness-dead.rs b/src/test/compile-fail/liveness-dead.rs
index 2ab3cb4568a..df78b25187b 100644
--- a/src/test/compile-fail/liveness-dead.rs
+++ b/src/test/compile-fail/liveness-dead.rs
@@ -15,14 +15,14 @@ fn f1(x: &mut int) {
 }
 
 fn f2() {
-    let mut x = 3; //~ ERROR: value assigned to `x` is never read
+    let mut x: int = 3; //~ ERROR: value assigned to `x` is never read
     x = 4;
-    copy x;
+    x.clone();
 }
 
 fn f3() {
-    let mut x = 3;
-    copy x;
+    let mut x: int = 3;
+    x.clone();
     x = 4; //~ ERROR: value assigned to `x` is never read
 }
 
diff --git a/src/test/compile-fail/liveness-init-in-fru.rs b/src/test/compile-fail/liveness-init-in-fru.rs
index 1bd42c1cd32..96b3c2453c5 100644
--- a/src/test/compile-fail/liveness-init-in-fru.rs
+++ b/src/test/compile-fail/liveness-init-in-fru.rs
@@ -9,11 +9,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-struct point {x: int, y: int}
+#[deriving(Clone)]
+struct point {
+    x: int,
+    y: int,
+}
 
 fn main() {
     let mut origin: point;
     origin = point {x: 10,.. origin}; //~ ERROR use of possibly uninitialized variable: `origin`
-    copy origin;
+    origin.clone();
 }
diff --git a/src/test/compile-fail/liveness-init-op-equal.rs b/src/test/compile-fail/liveness-init-op-equal.rs
index aa62e95b565..cbe805551c2 100644
--- a/src/test/compile-fail/liveness-init-op-equal.rs
+++ b/src/test/compile-fail/liveness-init-op-equal.rs
@@ -11,7 +11,7 @@
 fn test() {
     let v: int;
     v += 1; //~ ERROR use of possibly uninitialized variable: `v`
-    copy v;
+    v.clone();
 }
 
 fn main() {
diff --git a/src/test/compile-fail/liveness-init-plus-equal.rs b/src/test/compile-fail/liveness-init-plus-equal.rs
index fd9f7e01a26..6e813809f03 100644
--- a/src/test/compile-fail/liveness-init-plus-equal.rs
+++ b/src/test/compile-fail/liveness-init-plus-equal.rs
@@ -11,7 +11,7 @@
 fn test() {
     let mut v: int;
     v = v + 1; //~ ERROR use of possibly uninitialized variable: `v`
-    copy v;
+    v.clone();
 }
 
 fn main() {
diff --git a/src/test/compile-fail/liveness-move-in-loop.rs b/src/test/compile-fail/liveness-move-in-loop.rs
index 605233d3da0..b6cecf0145c 100644
--- a/src/test/compile-fail/liveness-move-in-loop.rs
+++ b/src/test/compile-fail/liveness-move-in-loop.rs
@@ -17,7 +17,7 @@ fn main() {
             loop {
                 loop {
                     x = y; //~ ERROR use of moved value
-                    copy x;
+                    x.clone();
                 }
             }
         }
diff --git a/src/test/compile-fail/liveness-move-in-while.rs b/src/test/compile-fail/liveness-move-in-while.rs
index c501607aee6..eed7ba16da4 100644
--- a/src/test/compile-fail/liveness-move-in-while.rs
+++ b/src/test/compile-fail/liveness-move-in-while.rs
@@ -14,7 +14,7 @@ fn main() {
     let mut x: ~int;
     loop {
         info!(y); //~ ERROR use of moved value: `y`
-        while true { while true { while true { x = y; copy x; } } }
+        while true { while true { while true { x = y; x.clone(); } } }
         //~^ ERROR use of moved value: `y`
     }
 }
diff --git a/src/test/compile-fail/liveness-use-after-move.rs b/src/test/compile-fail/liveness-use-after-move.rs
index 662514e133b..3423c780c4a 100644
--- a/src/test/compile-fail/liveness-use-after-move.rs
+++ b/src/test/compile-fail/liveness-use-after-move.rs
@@ -12,5 +12,5 @@ fn main() {
     let x = ~5;
     let y = x;
     info!(*x); //~ ERROR use of moved value: `x`
-    copy y;
+    y.clone();
 }
diff --git a/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs b/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs
index db52a2bbe1e..b70c9e11f34 100644
--- a/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs
+++ b/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs
@@ -18,25 +18,25 @@ fn f05() {
 
 fn f10() {
     let x = ~"hi";
-    let _y = Foo { f:copy x };
+    let _y = Foo { f:x.clone() };
     touch(&x);
 }
 
 fn f20() {
     let x = ~"hi";
-    let _y = Foo { f:copy (x) };
+    let _y = Foo { f:(x).clone() };
     touch(&x);
 }
 
 fn f30() {
     let x = ~"hi";
-    let _y = Foo { f:copy ((x)) };
+    let _y = Foo { f:((x)).clone() };
     touch(&x);
 }
 
 fn f40() {
     let x = ~"hi";
-    let _y = Foo { f:(((((copy ((x))))))) };
+    let _y = Foo { f:(((((((x)).clone()))))) };
     touch(&x);
 }
 
diff --git a/src/test/compile-fail/non-copyable-void.rs b/src/test/compile-fail/non-copyable-void.rs
index f979f8273a0..64d29a55756 100644
--- a/src/test/compile-fail/non-copyable-void.rs
+++ b/src/test/compile-fail/non-copyable-void.rs
@@ -14,7 +14,7 @@ fn main() {
     let x : *~[int] = &~[1,2,3];
     let y : *libc::c_void = x as *libc::c_void;
     unsafe {
-        let _z = copy *y;
-        //~^ ERROR copying a value of non-copyable type
+        let _z = (*y).clone();
+        //~^ ERROR does not implement any method in scope
     }
 }
diff --git a/src/test/compile-fail/noncopyable-class.rs b/src/test/compile-fail/noncopyable-class.rs
index aa7100f0aad..e64d5b67ab7 100644
--- a/src/test/compile-fail/noncopyable-class.rs
+++ b/src/test/compile-fail/noncopyable-class.rs
@@ -38,6 +38,6 @@ fn foo(i:int) -> foo {
 
 fn main() {
     let x = foo(10);
-    let _y = copy x; //~ ERROR copying a value of non-copyable type
+    let _y = x.clone(); //~ ERROR does not implement any method in scope
     error!(x);
 }
diff --git a/src/test/compile-fail/pinned-deep-copy.rs b/src/test/compile-fail/pinned-deep-copy.rs
index b7fc2a64669..ccbe265000d 100644
--- a/src/test/compile-fail/pinned-deep-copy.rs
+++ b/src/test/compile-fail/pinned-deep-copy.rs
@@ -27,13 +27,16 @@ fn r(i: @mut int) -> r {
     }
 }
 
+struct A {
+    y: r,
+}
+
 fn main() {
     let i = @mut 0;
     {
-        struct A { y: r }
         // Can't do this copy
         let x = ~~~A {y: r(i)};
-        let _z = copy x; //~ ERROR copying a value of non-copyable type
+        let _z = x.clone(); //~ ERROR failed to find an implementation
         info!(x);
     }
     error!(*i);
diff --git a/src/test/compile-fail/unique-object-noncopyable.rs b/src/test/compile-fail/unique-object-noncopyable.rs
index dacfd466040..ace0f516eef 100644
--- a/src/test/compile-fail/unique-object-noncopyable.rs
+++ b/src/test/compile-fail/unique-object-noncopyable.rs
@@ -29,5 +29,5 @@ impl Foo for Bar {
 fn main() {
     let x = ~Bar { x: 10 };
     let y: ~Foo = x as ~Foo;
-    let _z = copy y; //~ ERROR copying a value of non-copyable type
+    let _z = y.clone(); //~ ERROR does not implement any method in scope
 }
diff --git a/src/test/compile-fail/unique-pinned-nocopy.rs b/src/test/compile-fail/unique-pinned-nocopy.rs
index 30848a18af7..0218899bf2e 100644
--- a/src/test/compile-fail/unique-pinned-nocopy.rs
+++ b/src/test/compile-fail/unique-pinned-nocopy.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 struct r {
-  b:bool,
+  b: bool,
 }
 
 impl Drop for r {
@@ -18,6 +18,6 @@ impl Drop for r {
 
 fn main() {
     let i = ~r { b: true };
-    let _j = copy i; //~ ERROR copying a value of non-copyable type
+    let _j = i.clone(); //~ ERROR failed to find an implementation
     info!(i);
 }
diff --git a/src/test/compile-fail/unique-vec-res.rs b/src/test/compile-fail/unique-vec-res.rs
index cfb51793822..bee36ea8293 100644
--- a/src/test/compile-fail/unique-vec-res.rs
+++ b/src/test/compile-fail/unique-vec-res.rs
@@ -29,9 +29,8 @@ fn main() {
     let i2 = @mut 1;
     let r1 = ~[~r { i: i1 }];
     let r2 = ~[~r { i: i2 }];
-    f(copy r1, copy r2);
-    //~^ ERROR copying a value of non-copyable type
-    //~^^ ERROR copying a value of non-copyable type
+    f(r1.clone(), r2.clone());
+    //~^ ERROR failed to find an implementation of
     info!((r2, *i1));
     info!((r1, *i2));
 }
diff --git a/src/test/run-fail/unwind-box-fn-unique.rs b/src/test/run-fail/unwind-box-fn-unique.rs
index 4ab74b485ab..38a72353a1e 100644
--- a/src/test/run-fail/unwind-box-fn-unique.rs
+++ b/src/test/run-fail/unwind-box-fn-unique.rs
@@ -17,7 +17,7 @@ fn failfn() {
 fn main() {
     let y = ~0;
     let x: @~fn() = @(|| {
-        error!(copy y);
+        error!(y.clone());
     });
     failfn();
     error!(x);
diff --git a/src/test/run-fail/unwind-box-fn.rs b/src/test/run-fail/unwind-box-fn.rs
index c62e13e77d7..a94f904c492 100644
--- a/src/test/run-fail/unwind-box-fn.rs
+++ b/src/test/run-fail/unwind-box-fn.rs
@@ -17,7 +17,7 @@ fn failfn() {
 fn main() {
     let y = ~0;
     let x: @@fn() = @|| {
-        error!(copy y);
+        error!(y.clone());
     };
     failfn();
     error!(x);
diff --git a/src/test/run-fail/unwind-lambda.rs b/src/test/run-fail/unwind-lambda.rs
index 75c3638a99d..640be6635ee 100644
--- a/src/test/run-fail/unwind-lambda.rs
+++ b/src/test/run-fail/unwind-lambda.rs
@@ -15,11 +15,11 @@ fn main() {
     let carrots = @~"crunchy";
 
     let result: @fn(@~str, &fn(~str)) = (|tasties, macerate| {
-        macerate(copy *tasties);
+        macerate((*tasties).clone());
     });
     result(carrots, |food| {
         let mush = food + cheese;
-        let cheese = copy cheese;
+        let cheese = cheese.clone();
         let f: &fn() = || {
             let chew = mush + cheese;
             fail!("so yummy")
diff --git a/src/test/run-fail/unwind-misc-1.rs b/src/test/run-fail/unwind-misc-1.rs
index e30054575d6..75af701cede 100644
--- a/src/test/run-fail/unwind-misc-1.rs
+++ b/src/test/run-fail/unwind-misc-1.rs
@@ -18,7 +18,7 @@ fn main() {
     let mut arr = ~[];
     for uint::range(0u, 10u) |i| {
         arr += ~[@~"key stuff"];
-        map.insert(copy arr, arr + ~[@~"value stuff"]);
+        map.insert(arr.clone(), arr + ~[@~"value stuff"]);
         if arr.len() == 5 {
             fail!();
         }
diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs
index c48fbbca2b7..a821e4647c1 100644
--- a/src/test/run-pass/alignment-gep-tup-like-1.rs
+++ b/src/test/run-pass/alignment-gep-tup-like-1.rs
@@ -12,8 +12,8 @@ struct pair<A,B> {
     a: A, b: B
 }
 
-fn f<A:Copy + 'static>(a: A, b: u16) -> @fn() -> (A, u16) {
-    let result: @fn() -> (A, u16) = || (copy a, b);
+fn f<A:Clone + 'static>(a: A, b: u16) -> @fn() -> (A, u16) {
+    let result: @fn() -> (A, u16) = || (a.clone(), b);
     result
 }
 
diff --git a/src/test/run-pass/alignment-gep-tup-like-2.rs b/src/test/run-pass/alignment-gep-tup-like-2.rs
index f0f86222a25..1d910023a63 100644
--- a/src/test/run-pass/alignment-gep-tup-like-2.rs
+++ b/src/test/run-pass/alignment-gep-tup-like-2.rs
@@ -18,13 +18,13 @@ struct Rec<A> {
     rec: Option<@mut RecEnum<A>>
 }
 
-fn make_cycle<A:Copy>(a: A) {
+fn make_cycle<A>(a: A) {
     let g: @mut RecEnum<A> = @mut RecEnum(Rec {val: a, rec: None});
     g.rec = Some(g);
 }
 
-fn f<A:Send + Copy,B:Send + Copy>(a: A, b: B) -> @fn() -> (A, B) {
-    let result: @fn() -> (A, B) = || (copy a, copy b);
+fn f<A:Send + Clone,B:Send + Clone>(a: A, b: B) -> @fn() -> (A, B) {
+    let result: @fn() -> (A, B) = || (a.clone(), b.clone());
     result
 }
 
diff --git a/src/test/run-pass/borrowed-ptr-pattern.rs b/src/test/run-pass/borrowed-ptr-pattern.rs
index 86e8f600cd5..11751ed6ade 100644
--- a/src/test/run-pass/borrowed-ptr-pattern.rs
+++ b/src/test/run-pass/borrowed-ptr-pattern.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn foo<T:Copy>(x: &T) -> T{
+fn foo<T:Clone>(x: &T) -> T{
     match x {
-        &ref a => copy *a
+        &ref a => (*a).clone()
     }
 }
 
diff --git a/src/test/run-pass/box-unbox.rs b/src/test/run-pass/box-unbox.rs
index 2c45ec83d00..2e92395d549 100644
--- a/src/test/run-pass/box-unbox.rs
+++ b/src/test/run-pass/box-unbox.rs
@@ -12,7 +12,7 @@
 
 struct Box<T> {c: @T}
 
-fn unbox<T:Copy>(b: Box<T>) -> T { return copy *b.c; }
+fn unbox<T:Clone>(b: Box<T>) -> T { return (*b.c).clone(); }
 
 pub fn main() {
     let foo: int = 17;
diff --git a/src/test/run-pass/class-cast-to-trait-multiple-types.rs b/src/test/run-pass/class-cast-to-trait-multiple-types.rs
index 56c70e78092..97bcd7c5308 100644
--- a/src/test/run-pass/class-cast-to-trait-multiple-types.rs
+++ b/src/test/run-pass/class-cast-to-trait-multiple-types.rs
@@ -46,6 +46,7 @@ fn dog() -> dog {
     }
 }
 
+#[deriving(Clone)]
 struct cat {
   priv meows : @mut uint,
 
@@ -88,7 +89,7 @@ fn annoy_neighbors(critter: @noisy) {
 pub fn main() {
   let nyan : cat  = cat(0u, 2, ~"nyan");
   let whitefang : dog = dog();
-  annoy_neighbors(@(copy nyan) as @noisy);
+  annoy_neighbors(@nyan.clone() as @noisy);
   annoy_neighbors(@whitefang as @noisy);
   assert_eq!(nyan.meow_count(), 10u);
   assert_eq!(*whitefang.volume, 1);
diff --git a/src/test/run-pass/class-implement-traits.rs b/src/test/run-pass/class-implement-traits.rs
index 8c7c62ce27e..59de9e9e76e 100644
--- a/src/test/run-pass/class-implement-traits.rs
+++ b/src/test/run-pass/class-implement-traits.rs
@@ -16,6 +16,7 @@ trait noisy {
   fn speak(&mut self);
 }
 
+#[deriving(Clone)]
 struct cat {
     priv meows : uint,
 
@@ -68,6 +69,6 @@ pub fn main() {
   nyan.eat();
   assert!((!nyan.eat()));
   for uint::range(1u, 10u) |_i| {
-    make_speak(copy nyan);
+    make_speak(nyan.clone());
   }
 }
diff --git a/src/test/run-pass/close-over-big-then-small-data.rs b/src/test/run-pass/close-over-big-then-small-data.rs
index 1fa10222543..01c6442fa00 100644
--- a/src/test/run-pass/close-over-big-then-small-data.rs
+++ b/src/test/run-pass/close-over-big-then-small-data.rs
@@ -16,8 +16,8 @@ struct Pair<A,B> {
     a: A, b: B
 }
 
-fn f<A:Copy + 'static>(a: A, b: u16) -> @fn() -> (A, u16) {
-    let result: @fn() -> (A, u16) = || (copy a, b);
+fn f<A:Clone + 'static>(a: A, b: u16) -> @fn() -> (A, u16) {
+    let result: @fn() -> (A, u16) = || (a.clone(), b);
     result
 }
 
diff --git a/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs b/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs
deleted file mode 100644
index 8c2ae22e8ed..00000000000
--- a/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Tests correct copying of heap closures' environments.
-
-fn foo(x: ~fn:Copy()) -> (~fn:(), ~fn:()) {
-    (copy x, x)
-}
-fn main() {
-    let v = ~[~[1,2,3],~[4,5,6]]; // shouldn't get double-freed
-    let (f1,f2) = do foo {
-        assert!(v.len() == 2);
-    };
-    f1();
-    f2();
-}
diff --git a/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs b/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs
deleted file mode 100644
index 88d474a51e1..00000000000
--- a/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Tests correct copying of heap closures' environments.
-
-fn bar<T: Copy>(x: T) -> (T, T) {
-    (copy x, x)
-}
-fn foo(x: ~fn:Copy()) -> (~fn:(), ~fn:()) {
-    bar(x)
-}
-fn main() {
-    let v = ~[~[1,2,3],~[4,5,6]]; // shouldn't get double-freed
-    let (f1,f2) = do foo {
-        assert!(v.len() == 2);
-    };
-    f1();
-    f2();
-}
diff --git a/src/test/run-pass/explicit-self.rs b/src/test/run-pass/explicit-self.rs
index 9a4519786e9..295f175fca4 100644
--- a/src/test/run-pass/explicit-self.rs
+++ b/src/test/run-pass/explicit-self.rs
@@ -41,12 +41,15 @@ fn select_based_on_unit_circle<'r, T>(
     shape.select(threshold, a, b)
 }
 
-
+#[deriving(Clone)]
 struct thing {
     x: A
 }
 
-struct A { a: @int }
+#[deriving(Clone)]
+struct A {
+    a: @int
+}
 
 fn thing(x: A) -> thing {
     thing {
@@ -72,7 +75,7 @@ pub fn main() {
     assert_eq!(x.quux(), 10);
 
     let y = ~thing(A {a: @10});
-    assert_eq!((copy y).bar(), 10);
+    assert_eq!(y.clone().bar(), 10);
     assert_eq!(y.quux(), 10);
 
     let z = thing(A {a: @11});
diff --git a/src/test/run-pass/expr-block-generic-box2.rs b/src/test/run-pass/expr-block-generic-box2.rs
index 9cf047d425c..7d849bbff01 100644
--- a/src/test/run-pass/expr-block-generic-box2.rs
+++ b/src/test/run-pass/expr-block-generic-box2.rs
@@ -13,8 +13,8 @@
 
 type compare<T> = @fn(T, T) -> bool;
 
-fn test_generic<T:Copy>(expected: T, eq: compare<T>) {
-    let actual: T = { copy expected };
+fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
+    let actual: T = { expected.clone() };
     assert!((eq(expected, actual)));
 }
 
diff --git a/src/test/run-pass/expr-block-generic-unique2.rs b/src/test/run-pass/expr-block-generic-unique2.rs
index 25bf553ff35..389a42ae7af 100644
--- a/src/test/run-pass/expr-block-generic-unique2.rs
+++ b/src/test/run-pass/expr-block-generic-unique2.rs
@@ -13,8 +13,8 @@
 
 type compare<T> = @fn(T, T) -> bool;
 
-fn test_generic<T:Copy>(expected: T, eq: compare<T>) {
-    let actual: T = { copy expected };
+fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
+    let actual: T = { expected.clone() };
     assert!((eq(expected, actual)));
 }
 
diff --git a/src/test/run-pass/expr-block-generic.rs b/src/test/run-pass/expr-block-generic.rs
index afb1a4c76bb..7091fceb771 100644
--- a/src/test/run-pass/expr-block-generic.rs
+++ b/src/test/run-pass/expr-block-generic.rs
@@ -15,8 +15,8 @@
 // Tests for standalone blocks as expressions with dynamic type sizes
 type compare<T> = @fn(T, T) -> bool;
 
-fn test_generic<T:Copy>(expected: T, eq: compare<T>) {
-    let actual: T = { copy expected };
+fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
+    let actual: T = { expected.clone() };
     assert!((eq(expected, actual)));
 }
 
@@ -25,7 +25,11 @@ fn test_bool() {
     test_generic::<bool>(true, compare_bool);
 }
 
-struct Pair {a: int, b: int}
+#[deriving(Clone)]
+struct Pair {
+    a: int,
+    b: int,
+}
 
 fn test_rec() {
     fn compare_rec(t1: Pair, t2: Pair) -> bool {
diff --git a/src/test/run-pass/expr-if-generic-box2.rs b/src/test/run-pass/expr-if-generic-box2.rs
index 186d15c3490..a2d28a2be04 100644
--- a/src/test/run-pass/expr-if-generic-box2.rs
+++ b/src/test/run-pass/expr-if-generic-box2.rs
@@ -13,8 +13,8 @@
 
 type compare<T> = @fn(T, T) -> bool;
 
-fn test_generic<T:Copy>(expected: T, not_expected: T, eq: compare<T>) {
-    let actual: T = if true { copy expected } else { not_expected };
+fn test_generic<T:Clone>(expected: T, not_expected: T, eq: compare<T>) {
+    let actual: T = if true { expected.clone() } else { not_expected };
     assert!((eq(expected, actual)));
 }
 
diff --git a/src/test/run-pass/expr-if-generic.rs b/src/test/run-pass/expr-if-generic.rs
index 2e6db3bba07..f5b2a1a7986 100644
--- a/src/test/run-pass/expr-if-generic.rs
+++ b/src/test/run-pass/expr-if-generic.rs
@@ -14,8 +14,8 @@
 // Tests for if as expressions with dynamic type sizes
 type compare<T> = @fn(T, T) -> bool;
 
-fn test_generic<T:Copy>(expected: T, not_expected: T, eq: compare<T>) {
-    let actual: T = if true { copy expected } else { not_expected };
+fn test_generic<T:Clone>(expected: T, not_expected: T, eq: compare<T>) {
+    let actual: T = if true { expected.clone() } else { not_expected };
     assert!((eq(expected, actual)));
 }
 
@@ -24,7 +24,11 @@ fn test_bool() {
     test_generic::<bool>(true, false, compare_bool);
 }
 
-struct Pair {a: int, b: int}
+#[deriving(Clone)]
+struct Pair {
+    a: int,
+    b: int,
+}
 
 fn test_rec() {
     fn compare_rec(t1: Pair, t2: Pair) -> bool {
diff --git a/src/test/run-pass/expr-match-generic-box2.rs b/src/test/run-pass/expr-match-generic-box2.rs
index 64aa4ce3609..a2ccf5c0fb9 100644
--- a/src/test/run-pass/expr-match-generic-box2.rs
+++ b/src/test/run-pass/expr-match-generic-box2.rs
@@ -13,8 +13,8 @@
 
 type compare<T> = @fn(T, T) -> bool;
 
-fn test_generic<T:Copy>(expected: T, eq: compare<T>) {
-    let actual: T = match true { true => { copy expected }, _ => fail!("wat") };
+fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
+    let actual: T = match true { true => { expected.clone() }, _ => fail!("wat") };
     assert!((eq(expected, actual)));
 }
 
diff --git a/src/test/run-pass/expr-match-generic.rs b/src/test/run-pass/expr-match-generic.rs
index bd87e7207d1..59f1ff14f59 100644
--- a/src/test/run-pass/expr-match-generic.rs
+++ b/src/test/run-pass/expr-match-generic.rs
@@ -13,8 +13,8 @@
 
 type compare<T> = @fn(T, T) -> bool;
 
-fn test_generic<T:Copy>(expected: T, eq: compare<T>) {
-  let actual: T = match true { true => { copy expected }, _ => fail!("wat") };
+fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
+  let actual: T = match true { true => { expected.clone() }, _ => fail!("wat") };
     assert!((eq(expected, actual)));
 }
 
@@ -23,7 +23,11 @@ fn test_bool() {
     test_generic::<bool>(true, compare_bool);
 }
 
-struct Pair { a: int, b: int }
+#[deriving(Clone)]
+struct Pair {
+    a: int,
+    b: int,
+}
 
 fn test_rec() {
     fn compare_rec(t1: Pair, t2: Pair) -> bool {
diff --git a/src/test/run-pass/generic-derived-type.rs b/src/test/run-pass/generic-derived-type.rs
index 8d31c3d2481..3c30a6b53af 100644
--- a/src/test/run-pass/generic-derived-type.rs
+++ b/src/test/run-pass/generic-derived-type.rs
@@ -10,12 +10,16 @@
 
 
 
-fn g<X:Copy>(x: X) -> X { return x; }
+fn g<X>(x: X) -> X { return x; }
 
-struct Pair<T> {a: T, b: T}
+#[deriving(Clone)]
+struct Pair<T> {
+    a: T,
+    b: T
+}
 
-fn f<T:Copy>(t: T) -> Pair<T> {
-    let x: Pair<T> = Pair {a: copy t, b: t};
+fn f<T:Clone>(t: T) -> Pair<T> {
+    let x: Pair<T> = Pair {a: t.clone(), b: t};
     return g::<Pair<T>>(x);
 }
 
diff --git a/src/test/run-pass/getopts_ref.rs b/src/test/run-pass/getopts_ref.rs
index 3be685c6389..161f37eb444 100644
--- a/src/test/run-pass/getopts_ref.rs
+++ b/src/test/run-pass/getopts_ref.rs
@@ -21,7 +21,7 @@ pub fn main() {
     match getopts(args, opts) {
         Ok(ref m)  =>
             assert!(!opt_present(m, "b")),
-        Err(ref f) => fail!(fail_str(copy *f))
+        Err(ref f) => fail!(fail_str((*f).clone()))
     };
 
 }
diff --git a/src/test/run-pass/issue-2804.rs b/src/test/run-pass/issue-2804.rs
index 59ab5018c1d..aa9be2203c6 100644
--- a/src/test/run-pass/issue-2804.rs
+++ b/src/test/run-pass/issue-2804.rs
@@ -23,19 +23,15 @@ enum object {
 
 fn lookup(table: ~json::Object, key: ~str, default: ~str) -> ~str
 {
-    match table.find(&key)
-    {
-        option::Some(&extra::json::String(ref s)) =>
-        {
-            copy *s
+    match table.find(&key) {
+        option::Some(&extra::json::String(ref s)) => {
+            (*s).clone()
         }
-        option::Some(value) =>
-        {
+        option::Some(value) => {
             error!("%s was expected to be a string but is a %?", key, value);
             default
         }
-        option::None =>
-        {
+        option::None => {
             default
         }
     }
@@ -43,17 +39,14 @@ fn lookup(table: ~json::Object, key: ~str, default: ~str) -> ~str
 
 fn add_interface(store: int, managed_ip: ~str, data: extra::json::Json) -> (~str, object)
 {
-    match &data
-    {
-        &extra::json::Object(ref interface) =>
-        {
-            let name = lookup(copy *interface, ~"ifDescr", ~"");
+    match &data {
+        &extra::json::Object(ref interface) => {
+            let name = lookup((*interface).clone(), ~"ifDescr", ~"");
             let label = fmt!("%s-%s", managed_ip, name);
 
             (label, bool_value(false))
         }
-        _ =>
-        {
+        _ => {
             error!("Expected dict for %s interfaces but found %?", managed_ip, data);
             (~"gnos:missing-interface", bool_value(true))
         }
@@ -67,7 +60,7 @@ fn add_interfaces(store: int, managed_ip: ~str, device: HashMap<~str, extra::jso
         &extra::json::List(ref interfaces) =>
         {
           do interfaces.map |interface| {
-                add_interface(store, copy managed_ip, copy *interface)
+                add_interface(store, managed_ip.clone(), (*interface).clone())
           }
         }
         _ =>
diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs
index 5b668d710dd..387b0a68d21 100644
--- a/src/test/run-pass/issue-4241.rs
+++ b/src/test/run-pass/issue-4241.rs
@@ -103,7 +103,7 @@ priv fn cmd_to_str(cmd: ~[~str]) -> ~str {
   res.push_str("\r\n");
     for cmd.iter().advance |s| {
     res.push_str([~"$", s.len().to_str(), ~"\r\n",
-                  copy *s, ~"\r\n"].concat() );
+                  (*s).clone(), ~"\r\n"].concat() );
     }
   res
 }
diff --git a/src/test/run-pass/ivec-add.rs b/src/test/run-pass/ivec-add.rs
index 590be377691..61c63245d70 100644
--- a/src/test/run-pass/ivec-add.rs
+++ b/src/test/run-pass/ivec-add.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn double<T:Copy>(a: T) -> ~[T] { return ~[copy a] + ~[a]; }
+fn double<T:Copy + Clone>(a: T) -> ~[T] { return ~[a.clone()] + ~[a]; }
 
 fn double_int(a: int) -> ~[int] { return ~[a] + ~[a]; }
 
diff --git a/src/test/run-pass/kindck-owned-trait-contains-1.rs b/src/test/run-pass/kindck-owned-trait-contains-1.rs
index e733400527b..1370aea6df5 100644
--- a/src/test/run-pass/kindck-owned-trait-contains-1.rs
+++ b/src/test/run-pass/kindck-owned-trait-contains-1.rs
@@ -10,11 +10,13 @@
 
 trait repeat<A> { fn get(&self) -> A; }
 
-impl<A:Copy> repeat<A> for @A {
-    fn get(&self) -> A { copy **self }
+impl<A:Clone> repeat<A> for @A {
+    fn get(&self) -> A {
+        (**self).clone()
+    }
 }
 
-fn repeater<A:Copy>(v: @A) -> @repeat:<A> {
+fn repeater<A:Clone>(v: @A) -> @repeat:<A> {
     // Note: owned kind is not necessary as A appears in the trait type
     @v as @repeat:<A> // No
 }
diff --git a/src/test/run-pass/move-1-unique.rs b/src/test/run-pass/move-1-unique.rs
index 9194fc830e0..ac6dfa00f48 100644
--- a/src/test/run-pass/move-1-unique.rs
+++ b/src/test/run-pass/move-1-unique.rs
@@ -8,7 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct Triple { x: int, y: int, z: int }
+#[deriving(Clone)]
+struct Triple {
+    x: int,
+    y: int,
+    z: int,
+}
 
 fn test(x: bool, foo: ~Triple) -> int {
     let bar = foo;
@@ -19,8 +24,8 @@ fn test(x: bool, foo: ~Triple) -> int {
 
 pub fn main() {
     let x = ~Triple{x: 1, y: 2, z: 3};
-    assert_eq!(test(true, copy x), 2);
-    assert_eq!(test(true, copy x), 2);
-    assert_eq!(test(true, copy x), 2);
+    assert_eq!(test(true, x.clone()), 2);
+    assert_eq!(test(true, x.clone()), 2);
+    assert_eq!(test(true, x.clone()), 2);
     assert_eq!(test(false, x), 5);
 }
diff --git a/src/test/run-pass/move-3-unique.rs b/src/test/run-pass/move-3-unique.rs
index 1df2e3a382d..377fae52f49 100644
--- a/src/test/run-pass/move-3-unique.rs
+++ b/src/test/run-pass/move-3-unique.rs
@@ -12,7 +12,12 @@ extern mod extra;
 
 use std::uint;
 
-struct Triple { x: int, y: int, z: int }
+#[deriving(Clone)]
+struct Triple {
+    x: int,
+    y: int,
+    z: int,
+}
 
 fn test(x: bool, foo: ~Triple) -> int {
     let bar = foo;
@@ -24,7 +29,7 @@ fn test(x: bool, foo: ~Triple) -> int {
 pub fn main() {
     let x = ~Triple{x: 1, y: 2, z: 3};
     for uint::range(0u, 10000u) |_i| {
-        assert_eq!(test(true, copy x), 2);
+        assert_eq!(test(true, x.clone()), 2);
     }
     assert_eq!(test(false, x), 5);
 }
diff --git a/src/test/run-pass/newtype-polymorphic.rs b/src/test/run-pass/newtype-polymorphic.rs
index f88c71bdf39..694773f4c7c 100644
--- a/src/test/run-pass/newtype-polymorphic.rs
+++ b/src/test/run-pass/newtype-polymorphic.rs
@@ -8,15 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[deriving(Clone)]
 struct myvec<X>(~[X]);
 
-fn myvec_deref<X:Copy>(mv: myvec<X>) -> ~[X] { return copy *mv; }
+fn myvec_deref<X:Clone>(mv: myvec<X>) -> ~[X] { return (*mv).clone(); }
 
-fn myvec_elt<X:Copy>(mv: myvec<X>) -> X { return mv[0]; }
+fn myvec_elt<X>(mv: myvec<X>) -> X { return mv[0]; }
 
 pub fn main() {
     let mv = myvec(~[1, 2, 3]);
-    assert_eq!(myvec_deref(copy mv)[1], 2);
-    assert_eq!(myvec_elt(copy mv), 1);
+    assert_eq!(myvec_deref(mv.clone())[1], 2);
+    assert_eq!(myvec_elt(mv.clone()), 1);
     assert_eq!(mv[2], 3);
 }
diff --git a/src/test/run-pass/nullable-pointer-iotareduction.rs b/src/test/run-pass/nullable-pointer-iotareduction.rs
index e557fae7ac9..62bd54e4395 100644
--- a/src/test/run-pass/nullable-pointer-iotareduction.rs
+++ b/src/test/run-pass/nullable-pointer-iotareduction.rs
@@ -1,3 +1,7 @@
+// xfail-test
+
+// xfail'd due to a bug in move detection for macros.
+
 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
@@ -36,11 +40,12 @@ impl<T> E<T> {
 
 macro_rules! check_option {
     ($e:expr: $T:ty) => {{
-        check_option!(copy $e: $T, |ptr| assert!(*ptr == $e));
+        check_option!($e: $T, |ptr| assert!(*ptr == $e));
     }};
     ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{
         assert!(option::None::<$T>.is_none());
-        let s_ = option::Some::<$T>($e);
+        let e = $e;
+        let s_ = option::Some::<$T>(e);
         let $v = s_.get_ref();
         $chk
     }}
@@ -48,11 +53,12 @@ macro_rules! check_option {
 
 macro_rules! check_fancy {
     ($e:expr: $T:ty) => {{
-        check_fancy!(copy $e: $T, |ptr| assert!(*ptr == $e));
+        check_fancy!($e: $T, |ptr| assert!(*ptr == $e));
     }};
     ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{
         assert!(Nothing::<$T>((), ((), ()), [23i8, ..0]).is_none());
-        let t_ = Thing::<$T>(23, $e);
+        let e = $e;
+        let t_ = Thing::<$T>(23, e);
         match t_.get_ref() {
             (23, $v) => { $chk }
             _ => fail!("Thing::<%s>(23, %s).get_ref() != (23, _)",
@@ -74,7 +80,6 @@ pub fn main() {
     check_type!(@19: @int);
     check_type!(~"foo": ~str);
     check_type!(@"bar": @str);
-    check_type!(~[]: ~[int]);
     check_type!(~[20, 22]: ~[int]);
     check_type!(@[]: @[int]);
     check_type!(@[24, 26]: @[int]);
diff --git a/src/test/run-pass/overload-index-operator.rs b/src/test/run-pass/overload-index-operator.rs
index b995e9c9ed2..824cacc620d 100644
--- a/src/test/run-pass/overload-index-operator.rs
+++ b/src/test/run-pass/overload-index-operator.rs
@@ -17,6 +17,7 @@ struct AssociationList<K,V> {
     pairs: ~[AssociationPair<K,V>]
 }
 
+#[deriving(Clone)]
 struct AssociationPair<K,V> {
     key: K,
     value: V
@@ -28,11 +29,11 @@ impl<K,V> AssociationList<K,V> {
     }
 }
 
-impl<K:Eq,V:Copy> Index<K,V> for AssociationList<K,V> {
+impl<K:Eq,V:Clone> Index<K,V> for AssociationList<K,V> {
     fn index(&self, index: &K) -> V {
         for self.pairs.iter().advance |pair| {
             if pair.key == *index {
-                return copy pair.value;
+                return pair.value.clone();
             }
         }
         fail!("No value found for key: %?", index);
@@ -44,8 +45,8 @@ pub fn main() {
     let bar = ~"bar";
 
     let mut list = AssociationList {pairs: ~[]};
-    list.push(copy foo, 22);
-    list.push(copy bar, 44);
+    list.push(foo.clone(), 22);
+    list.push(bar.clone(), 44);
 
     assert!(list[foo] == 22)
     assert!(list[bar] == 44)
diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs
index b7ef4e3ff25..faae814821d 100644
--- a/src/test/run-pass/reflect-visit-data.rs
+++ b/src/test/run-pass/reflect-visit-data.rs
@@ -499,9 +499,9 @@ struct Stuff {
 }
 
 impl my_visitor {
-    pub fn get<T:Copy>(&self, f: &fn(T)) {
+    pub fn get<T:Clone>(&self, f: &fn(T)) {
         unsafe {
-            f(copy *(self.ptr1 as *T));
+            f((*(self.ptr1 as *T)).clone());
         }
     }
 
diff --git a/src/test/run-pass/resource-generic.rs b/src/test/run-pass/resource-generic.rs
deleted file mode 100644
index 75d978b0d05..00000000000
--- a/src/test/run-pass/resource-generic.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// xfail-fast
-
-struct Arg<T> {val: T, fin: extern fn(T)}
-
-struct finish<T> {
-  arg: Arg<T>
-}
-
-#[unsafe_destructor]
-impl<T:Copy> Drop for finish<T> {
-    fn drop(&self) {
-        unsafe {
-            (self.arg.fin)(copy self.arg.val);
-        }
-    }
-}
-
-fn finish<T:Copy>(arg: Arg<T>) -> finish<T> {
-    finish {
-        arg: arg
-    }
-}
-
-pub fn main() {
-    let box = @mut 10;
-    fn dec_box(i: @mut int) { *i -= 1; }
-
-    { let _i = finish(Arg{val: box, fin: dec_box}); }
-    assert_eq!(*box, 9);
-}
diff --git a/src/test/run-pass/sendfn-generic-fn.rs b/src/test/run-pass/sendfn-generic-fn.rs
index b74e81bb612..e192a38dfa3 100644
--- a/src/test/run-pass/sendfn-generic-fn.rs
+++ b/src/test/run-pass/sendfn-generic-fn.rs
@@ -14,25 +14,29 @@ use std::task;
 
 pub fn main() { test05(); }
 
-struct Pair<A,B> { a: A, b: B }
+#[deriving(Clone)]
+struct Pair<A,B> {
+    a: A,
+    b: B,
+}
 
-fn make_generic_record<A:Copy,B:Copy>(a: A, b: B) -> Pair<A,B> {
+fn make_generic_record<A,B>(a: A, b: B) -> Pair<A,B> {
     return Pair {a: a, b: b};
 }
 
 fn test05_start(f: &~fn(v: float, v: ~str) -> Pair<float, ~str>) {
     let p = (*f)(22.22f, ~"Hi");
-    info!(copy p);
+    info!(p.clone());
     assert!(p.a == 22.22f);
     assert!(p.b == ~"Hi");
 
     let q = (*f)(44.44f, ~"Ho");
-    info!(copy q);
+    info!(q.clone());
     assert!(q.a == 44.44f);
     assert!(q.b == ~"Ho");
 }
 
-fn spawn<A:Copy,B:Copy>(f: extern fn(&~fn(A,B)->Pair<A,B>)) {
+fn spawn<A,B>(f: extern fn(&~fn(A,B)->Pair<A,B>)) {
     let arg: ~fn(A, B) -> Pair<A,B> = |a, b| make_generic_record(a, b);
     task::spawn(|| f(&arg));
 }
diff --git a/src/test/run-pass/shape_intrinsic_tag_then_rec.rs b/src/test/run-pass/shape_intrinsic_tag_then_rec.rs
index 34afc12f02e..11489c33eea 100644
--- a/src/test/run-pass/shape_intrinsic_tag_then_rec.rs
+++ b/src/test/run-pass/shape_intrinsic_tag_then_rec.rs
@@ -13,20 +13,43 @@
 // interior record which is then itself interior to
 // something else, shape calculations were off.
 
+#[deriving(Clone)]
 enum opt_span {
-
     //hack (as opposed to option), to make `span` compile
     os_none,
     os_some(@Span),
 }
-struct Span {lo: uint, hi: uint, expanded_from: opt_span}
-struct Spanned<T> { data: T, span: Span }
+
+#[deriving(Clone)]
+struct Span {
+    lo: uint,
+    hi: uint,
+    expanded_from: opt_span,
+}
+
+#[deriving(Clone)]
+struct Spanned<T> {
+    data: T,
+    span: Span,
+}
+
 type ty_ = uint;
-struct Path_ { global: bool, idents: ~[~str], types: ~[@ty] }
+
+#[deriving(Clone)]
+struct Path_ {
+    global: bool,
+    idents: ~[~str],
+    types: ~[@ty],
+}
+
 type path = Spanned<Path_>;
 type ty = Spanned<ty_>;
 
-struct X { sp: Span, path: path }
+#[deriving(Clone)]
+struct X {
+    sp: Span,
+    path: path,
+}
 
 pub fn main() {
     let sp: Span = Span {lo: 57451u, hi: 57542u, expanded_from: os_none};
@@ -34,6 +57,6 @@ pub fn main() {
     let p_: Path_ = Path_ { global: true, idents: ~[~"hi"], types: ~[t] };
     let p: path = Spanned { data: p_, span: sp };
     let x = X { sp: sp, path: p };
-    error!(copy x.path);
-    error!(copy x);
+    error!(x.path.clone());
+    error!(x.clone());
 }
diff --git a/src/test/run-pass/unique-copy-box.rs b/src/test/run-pass/unique-copy-box.rs
index 7634641a56e..3b3074b4a7d 100644
--- a/src/test/run-pass/unique-copy-box.rs
+++ b/src/test/run-pass/unique-copy-box.rs
@@ -15,7 +15,7 @@ pub fn main() {
         let i = ~@1;
         let j = ~@2;
         let rc1 = sys::refcount(*i);
-        let j = copy i;
+        let j = i.clone();
         let rc2 = sys::refcount(*i);
         error!("rc1: %u rc2: %u", rc1, rc2);
         assert_eq!(rc1 + 1u, rc2);