about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/lint/builtin.rs102
-rw-r--r--src/librustc/lint/context.rs1
-rw-r--r--src/librustc/lint/mod.rs8
-rw-r--r--src/librustc/metadata/common.rs2
-rw-r--r--src/librustc/metadata/creader.rs6
-rw-r--r--src/librustc/metadata/csearch.rs7
-rw-r--r--src/librustc/metadata/cstore.rs17
-rw-r--r--src/librustc/metadata/decoder.rs6
-rw-r--r--src/librustc/metadata/filesearch.rs7
-rw-r--r--src/librustc/metadata/tydecode.rs2
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs14
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs12
-rw-r--r--src/librustc/middle/borrowck/graphviz.rs2
-rw-r--r--src/librustc/middle/borrowck/mod.rs37
-rw-r--r--src/librustc/middle/borrowck/move_data.rs16
-rw-r--r--src/librustc/middle/cfg/construct.rs2
-rw-r--r--src/librustc/middle/cfg/mod.rs2
-rw-r--r--src/librustc/middle/check_loop.rs4
-rw-r--r--src/librustc/middle/check_match.rs26
-rw-r--r--src/librustc/middle/check_rvalues.rs6
-rw-r--r--src/librustc/middle/check_static.rs10
-rw-r--r--src/librustc/middle/const_eval.rs2
-rw-r--r--src/librustc/middle/dataflow.rs7
-rw-r--r--src/librustc/middle/def.rs4
-rw-r--r--src/librustc/middle/effect.rs2
-rw-r--r--src/librustc/middle/expr_use_visitor.rs69
-rw-r--r--src/librustc/middle/fast_reject.rs2
-rw-r--r--src/librustc/middle/graph.rs6
-rw-r--r--src/librustc/middle/infer/mod.rs6
-rw-r--r--src/librustc/middle/infer/region_inference/mod.rs16
-rw-r--r--src/librustc/middle/infer/type_variable.rs2
-rw-r--r--src/librustc/middle/infer/unify.rs2
-rw-r--r--src/librustc/middle/lang_items.rs2
-rw-r--r--src/librustc/middle/liveness.rs15
-rw-r--r--src/librustc/middle/mem_categorization.rs22
-rw-r--r--src/librustc/middle/region.rs4
-rw-r--r--src/librustc/middle/resolve.rs40
-rw-r--r--src/librustc/middle/resolve_lifetime.rs2
-rw-r--r--src/librustc/middle/subst.rs2
-rw-r--r--src/librustc/middle/traits/mod.rs8
-rw-r--r--src/librustc/middle/traits/select.rs29
-rw-r--r--src/librustc/middle/ty.rs229
-rw-r--r--src/librustc/session/config.rs12
-rw-r--r--src/librustc/util/common.rs2
-rw-r--r--src/librustc/util/nodemap.rs3
45 files changed, 667 insertions, 110 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index c474820c3c9..e19fa01b2e4 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -28,6 +28,7 @@ use self::MethodContext::*;
 
 use metadata::csearch;
 use middle::def::*;
+use middle::subst::Substs;
 use middle::ty::{mod, Ty};
 use middle::{def, pat_util, stability};
 use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
@@ -40,11 +41,12 @@ use std::collections::hash_map::{Occupied, Vacant};
 use std::num::SignedInt;
 use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 use syntax::{abi, ast, ast_map};
-use syntax::ast_util::{mod, is_shift_binop};
+use syntax::ast_util::is_shift_binop;
 use syntax::attr::{mod, AttrMetaMethods};
 use syntax::codemap::{Span, DUMMY_SP};
 use syntax::parse::token;
 use syntax::ast::{TyI, TyU, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
+use syntax::ast_util;
 use syntax::ptr::P;
 use syntax::visit::{mod, Visitor};
 
@@ -53,6 +55,8 @@ declare_lint!(WHILE_TRUE, Warn,
 
 pub struct WhileTrue;
 
+impl Copy for WhileTrue {}
+
 impl LintPass for WhileTrue {
     fn get_lints(&self) -> LintArray {
         lint_array!(WHILE_TRUE)
@@ -75,6 +79,8 @@ declare_lint!(UNUSED_TYPECASTS, Allow,
 
 pub struct UnusedCasts;
 
+impl Copy for UnusedCasts {}
+
 impl LintPass for UnusedCasts {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNUSED_TYPECASTS)
@@ -107,6 +113,8 @@ pub struct TypeLimits {
     negated_expr_id: ast::NodeId,
 }
 
+impl Copy for TypeLimits {}
+
 impl TypeLimits {
     pub fn new() -> TypeLimits {
         TypeLimits {
@@ -415,6 +423,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
 
 pub struct ImproperCTypes;
 
+impl Copy for ImproperCTypes {}
+
 impl LintPass for ImproperCTypes {
     fn get_lints(&self) -> LintArray {
         lint_array!(IMPROPER_CTYPES)
@@ -454,6 +464,8 @@ declare_lint!(BOX_POINTERS, Allow,
 
 pub struct BoxPointers;
 
+impl Copy for BoxPointers {}
+
 impl BoxPointers {
     fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>,
                                  span: Span, ty: Ty<'tcx>) {
@@ -587,6 +599,8 @@ declare_lint!(UNUSED_ATTRIBUTES, Warn,
 
 pub struct UnusedAttributes;
 
+impl Copy for UnusedAttributes {}
+
 impl LintPass for UnusedAttributes {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNUSED_ATTRIBUTES)
@@ -666,6 +680,8 @@ declare_lint!(pub PATH_STATEMENTS, Warn,
 
 pub struct PathStatements;
 
+impl Copy for PathStatements {}
+
 impl LintPass for PathStatements {
     fn get_lints(&self) -> LintArray {
         lint_array!(PATH_STATEMENTS)
@@ -693,6 +709,8 @@ declare_lint!(pub UNUSED_RESULTS, Allow,
 
 pub struct UnusedResults;
 
+impl Copy for UnusedResults {}
+
 impl LintPass for UnusedResults {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS)
@@ -757,6 +775,8 @@ declare_lint!(pub NON_CAMEL_CASE_TYPES, Warn,
 
 pub struct NonCamelCaseTypes;
 
+impl Copy for NonCamelCaseTypes {}
+
 impl NonCamelCaseTypes {
     fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
         fn is_camel_case(ident: ast::Ident) -> bool {
@@ -876,6 +896,8 @@ declare_lint!(pub NON_SNAKE_CASE, Warn,
 
 pub struct NonSnakeCase;
 
+impl Copy for NonSnakeCase {}
+
 impl NonSnakeCase {
     fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
         fn is_snake_case(ident: ast::Ident) -> bool {
@@ -985,6 +1007,8 @@ declare_lint!(pub NON_UPPER_CASE_GLOBALS, Warn,
 
 pub struct NonUpperCaseGlobals;
 
+impl Copy for NonUpperCaseGlobals {}
+
 impl LintPass for NonUpperCaseGlobals {
     fn get_lints(&self) -> LintArray {
         lint_array!(NON_UPPER_CASE_GLOBALS)
@@ -1034,6 +1058,8 @@ declare_lint!(UNUSED_PARENS, Warn,
 
 pub struct UnusedParens;
 
+impl Copy for UnusedParens {}
+
 impl UnusedParens {
     fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str,
                                      struct_lit_needs_parens: bool) {
@@ -1124,6 +1150,8 @@ declare_lint!(UNUSED_IMPORT_BRACES, Allow,
 
 pub struct UnusedImportBraces;
 
+impl Copy for UnusedImportBraces {}
+
 impl LintPass for UnusedImportBraces {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNUSED_IMPORT_BRACES)
@@ -1159,6 +1187,8 @@ declare_lint!(NON_SHORTHAND_FIELD_PATTERNS, Warn,
 
 pub struct NonShorthandFieldPatterns;
 
+impl Copy for NonShorthandFieldPatterns {}
+
 impl LintPass for NonShorthandFieldPatterns {
     fn get_lints(&self) -> LintArray {
         lint_array!(NON_SHORTHAND_FIELD_PATTERNS)
@@ -1188,6 +1218,8 @@ declare_lint!(pub UNUSED_UNSAFE, Warn,
 
 pub struct UnusedUnsafe;
 
+impl Copy for UnusedUnsafe {}
+
 impl LintPass for UnusedUnsafe {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNUSED_UNSAFE)
@@ -1209,6 +1241,8 @@ declare_lint!(UNSAFE_BLOCKS, Allow,
 
 pub struct UnsafeBlocks;
 
+impl Copy for UnsafeBlocks {}
+
 impl LintPass for UnsafeBlocks {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNSAFE_BLOCKS)
@@ -1229,6 +1263,8 @@ declare_lint!(pub UNUSED_MUT, Warn,
 
 pub struct UnusedMut;
 
+impl Copy for UnusedMut {}
+
 impl UnusedMut {
     fn check_unused_mut_pat(&self, cx: &Context, pats: &[P<ast::Pat>]) {
         // collect all mutable pattern and group their NodeIDs by their Identifier to
@@ -1294,6 +1330,8 @@ declare_lint!(UNUSED_ALLOCATION, Warn,
 
 pub struct UnusedAllocation;
 
+impl Copy for UnusedAllocation {}
+
 impl LintPass for UnusedAllocation {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNUSED_ALLOCATION)
@@ -1479,6 +1517,61 @@ impl LintPass for MissingDoc {
     }
 }
 
+pub struct MissingCopyImplementations;
+
+impl Copy for MissingCopyImplementations {}
+
+impl LintPass for MissingCopyImplementations {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(MISSING_COPY_IMPLEMENTATIONS)
+    }
+
+    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
+        if !cx.exported_items.contains(&item.id) {
+            return
+        }
+        if cx.tcx
+             .destructor_for_type
+             .borrow()
+             .contains_key(&ast_util::local_def(item.id)) {
+            return
+        }
+        let ty = match item.node {
+            ast::ItemStruct(_, ref ast_generics) => {
+                if ast_generics.is_parameterized() {
+                    return
+                }
+                ty::mk_struct(cx.tcx,
+                              ast_util::local_def(item.id),
+                              Substs::empty())
+            }
+            ast::ItemEnum(_, ref ast_generics) => {
+                if ast_generics.is_parameterized() {
+                    return
+                }
+                ty::mk_enum(cx.tcx,
+                            ast_util::local_def(item.id),
+                            Substs::empty())
+            }
+            _ => return,
+        };
+        let parameter_environment = ty::empty_parameter_environment();
+        if !ty::type_moves_by_default(cx.tcx,
+                                      ty,
+                                      &parameter_environment) {
+            return
+        }
+        if ty::can_type_implement_copy(cx.tcx,
+                                       ty,
+                                       &parameter_environment).is_ok() {
+            cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
+                         item.span,
+                         "type could implement `Copy`; consider adding `impl \
+                          Copy`")
+        }
+    }
+}
+
 declare_lint!(DEPRECATED, Warn,
               "detects use of #[deprecated] items")
 
@@ -1493,6 +1586,8 @@ declare_lint!(UNSTABLE, Allow,
 /// `#[unstable]` attributes, or no stability attribute.
 pub struct Stability;
 
+impl Copy for Stability {}
+
 impl Stability {
     fn lint(&self, cx: &Context, id: ast::DefId, span: Span) {
         let stability = stability::lookup(cx.tcx, id);
@@ -1682,10 +1777,15 @@ declare_lint!(pub VARIANT_SIZE_DIFFERENCES, Allow,
 declare_lint!(pub FAT_PTR_TRANSMUTES, Allow,
               "detects transmutes of fat pointers")
 
+declare_lint!(pub MISSING_COPY_IMPLEMENTATIONS, Warn,
+              "detects potentially-forgotten implementations of `Copy`")
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 pub struct HardwiredLints;
 
+impl Copy for HardwiredLints {}
+
 impl LintPass for HardwiredLints {
     fn get_lints(&self) -> LintArray {
         lint_array!(
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 442d3aab92d..153a00e5617 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -204,6 +204,7 @@ impl LintStore {
                      UnusedMut,
                      UnusedAllocation,
                      Stability,
+                     MissingCopyImplementations,
         )
 
         add_builtin_with_new!(sess,
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index d6b83752cc5..4b4ba2ab94c 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -64,6 +64,8 @@ pub struct Lint {
     pub desc: &'static str,
 }
 
+impl Copy for Lint {}
+
 impl Lint {
     /// Get the lint's name, with ASCII letters converted to lowercase.
     pub fn name_lower(&self) -> String {
@@ -179,6 +181,8 @@ pub struct LintId {
     lint: &'static Lint,
 }
 
+impl Copy for LintId {}
+
 impl PartialEq for LintId {
     fn eq(&self, other: &LintId) -> bool {
         (self.lint as *const Lint) == (other.lint as *const Lint)
@@ -214,6 +218,8 @@ pub enum Level {
     Allow, Warn, Deny, Forbid
 }
 
+impl Copy for Level {}
+
 impl Level {
     /// Convert a level to a lower-case string.
     pub fn as_str(self) -> &'static str {
@@ -251,6 +257,8 @@ pub enum LintSource {
     CommandLine,
 }
 
+impl Copy for LintSource {}
+
 pub type LevelSource = (Level, LintSource);
 
 pub mod builtin;
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index 0da3b1b7a4e..315e0eea9b7 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -144,6 +144,8 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
     tag_table_capture_modes = 0x56,
     tag_table_object_cast_map = 0x57,
 }
+
+impl Copy for astencode_tag {}
 static first_astencode_tag: uint = tag_ast as uint;
 static last_astencode_tag: uint = tag_table_object_cast_map as uint;
 impl astencode_tag {
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index deeab18de7c..9e87153e64a 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -275,8 +275,10 @@ fn visit_item(e: &Env, i: &ast::Item) {
     }
 }
 
-fn register_native_lib(sess: &Session, span: Option<Span>, name: String,
-                       kind: cstore::NativeLibaryKind) {
+fn register_native_lib(sess: &Session,
+                       span: Option<Span>,
+                       name: String,
+                       kind: cstore::NativeLibraryKind) {
     if name.is_empty() {
         match span {
             Some(span) => {
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index ebf5cca6a31..b864dc39603 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -40,6 +40,8 @@ pub struct MethodInfo {
     pub vis: ast::Visibility,
 }
 
+impl Copy for MethodInfo {}
+
 pub fn get_symbol(cstore: &cstore::CStore, def: ast::DefId) -> String {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_symbol(cdata.data(), def.node)
@@ -273,9 +275,8 @@ pub fn get_impl_vtables<'tcx>(tcx: &ty::ctxt<'tcx>,
     decoder::get_impl_vtables(&*cdata, def.node, tcx)
 }
 
-pub fn get_native_libraries(cstore: &cstore::CStore,
-                            crate_num: ast::CrateNum)
-                                -> Vec<(cstore::NativeLibaryKind, String)> {
+pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
+                            -> Vec<(cstore::NativeLibraryKind, String)> {
     let cdata = cstore.get_crate_data(crate_num);
     decoder::get_native_libraries(&*cdata)
 }
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index f93a1699e18..91f360a7a38 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -15,7 +15,7 @@
 
 pub use self::MetadataBlob::*;
 pub use self::LinkagePreference::*;
-pub use self::NativeLibaryKind::*;
+pub use self::NativeLibraryKind::*;
 
 use back::svh::Svh;
 use metadata::decoder;
@@ -54,13 +54,17 @@ pub enum LinkagePreference {
     RequireStatic,
 }
 
-#[deriving(PartialEq, FromPrimitive, Clone)]
-pub enum NativeLibaryKind {
+impl Copy for LinkagePreference {}
+
+#[deriving(Clone, PartialEq, FromPrimitive)]
+pub enum NativeLibraryKind {
     NativeStatic,    // native static library (.a archive)
     NativeFramework, // OSX-specific
     NativeUnknown,   // default way to specify a dynamic library
 }
 
+impl Copy for NativeLibraryKind {}
+
 // Where a crate came from on the local filesystem. One of these two options
 // must be non-None.
 #[deriving(PartialEq, Clone)]
@@ -75,7 +79,7 @@ pub struct CStore {
     /// Map from NodeId's of local extern crate statements to crate numbers
     extern_mod_crate_map: RefCell<NodeMap<ast::CrateNum>>,
     used_crate_sources: RefCell<Vec<CrateSource>>,
-    used_libraries: RefCell<Vec<(String, NativeLibaryKind)>>,
+    used_libraries: RefCell<Vec<(String, NativeLibraryKind)>>,
     used_link_args: RefCell<Vec<String>>,
     pub intr: Rc<IdentInterner>,
 }
@@ -186,13 +190,14 @@ impl CStore {
         libs
     }
 
-    pub fn add_used_library(&self, lib: String, kind: NativeLibaryKind) {
+    pub fn add_used_library(&self, lib: String, kind: NativeLibraryKind) {
         assert!(!lib.is_empty());
         self.used_libraries.borrow_mut().push((lib, kind));
     }
 
     pub fn get_used_libraries<'a>(&'a self)
-                              -> &'a RefCell<Vec<(String, NativeLibaryKind)> > {
+                              -> &'a RefCell<Vec<(String,
+                                                  NativeLibraryKind)>> {
         &self.used_libraries
     }
 
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index f352a28df69..0d51e044de9 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -442,6 +442,8 @@ pub enum DefLike {
     DlField
 }
 
+impl Copy for DefLike {}
+
 /// Iterates over the language items in the given crate.
 pub fn each_lang_item(cdata: Cmd, f: |ast::NodeId, uint| -> bool) -> bool {
     let root = rbml::Doc::new(cdata.data());
@@ -1267,14 +1269,14 @@ pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
 
 
 pub fn get_native_libraries(cdata: Cmd)
-                            -> Vec<(cstore::NativeLibaryKind, String)> {
+                            -> Vec<(cstore::NativeLibraryKind, String)> {
     let libraries = reader::get_doc(rbml::Doc::new(cdata.data()),
                                     tag_native_libraries);
     let mut result = Vec::new();
     reader::tagged_docs(libraries, tag_native_libraries_lib, |lib_doc| {
         let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind);
         let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name);
-        let kind: cstore::NativeLibaryKind =
+        let kind: cstore::NativeLibraryKind =
             FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
         let name = name_doc.as_str().to_string();
         result.push((kind, name));
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 63fc2af492c..2d23a61813a 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -20,7 +20,12 @@ use std::os;
 
 use util::fs as myfs;
 
-pub enum FileMatch { FileMatches, FileDoesntMatch }
+pub enum FileMatch {
+    FileMatches,
+    FileDoesntMatch,
+}
+
+impl Copy for FileMatch {}
 
 // A module for searching for libraries
 // FIXME (#2658): I'm not happy how this module turned out. Should
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 00d12ad6a38..e29741fb4a1 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -61,6 +61,8 @@ pub enum DefIdSource {
     // Identifies an unboxed closure
     UnboxedClosureSource
 }
+
+impl Copy for DefIdSource {}
 pub type conv_did<'a> =
     |source: DefIdSource, ast::DefId|: 'a -> ast::DefId;
 
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 72c6256dcb5..5f030324d42 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -24,7 +24,9 @@ use middle::borrowck::LoanPathKind::*;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
 use middle::region;
+use middle::ty::ParameterEnvironment;
 use middle::ty;
+use syntax::ast::NodeId;
 use syntax::ast;
 use syntax::codemap::Span;
 use util::ppaux::Repr;
@@ -89,6 +91,7 @@ struct CheckLoanCtxt<'a, 'tcx: 'a> {
     dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
     move_data: move_data::FlowedMoveData<'a, 'tcx>,
     all_loans: &'a [Loan<'tcx>],
+    param_env: &'a ParameterEnvironment<'tcx>,
 }
 
 impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
@@ -193,19 +196,25 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                      dfcx_loans: &LoanDataFlow<'b, 'tcx>,
                                      move_data: move_data::FlowedMoveData<'c, 'tcx>,
                                      all_loans: &[Loan<'tcx>],
+                                     fn_id: NodeId,
                                      decl: &ast::FnDecl,
                                      body: &ast::Block) {
     debug!("check_loans(body id={})", body.id);
 
+    let param_env = ParameterEnvironment::for_item(bccx.tcx, fn_id);
+
     let mut clcx = CheckLoanCtxt {
         bccx: bccx,
         dfcx_loans: dfcx_loans,
         move_data: move_data,
         all_loans: all_loans,
+        param_env: &param_env,
     };
 
     {
-        let mut euv = euv::ExprUseVisitor::new(&mut clcx, bccx.tcx);
+        let mut euv = euv::ExprUseVisitor::new(&mut clcx,
+                                               bccx.tcx,
+                                               param_env.clone());
         euv.walk_fn(decl, body);
     }
 }
@@ -700,7 +709,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                 use_kind,
                 &**lp,
                 the_move,
-                moved_lp);
+                moved_lp,
+                self.param_env);
             false
         });
     }
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index edffe59fff5..ca9d4b512b3 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -22,6 +22,7 @@ use middle::borrowck::move_data::MoveData;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
 use middle::region;
+use middle::ty::ParameterEnvironment;
 use middle::ty;
 use util::ppaux::{Repr};
 
@@ -37,10 +38,11 @@ mod gather_moves;
 mod move_error;
 
 pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
+                                    fn_id: NodeId,
                                     decl: &ast::FnDecl,
                                     body: &ast::Block)
-                                    -> (Vec<Loan<'tcx>>, move_data::MoveData<'tcx>)
-{
+                                    -> (Vec<Loan<'tcx>>,
+                                        move_data::MoveData<'tcx>) {
     let mut glcx = GatherLoanCtxt {
         bccx: bccx,
         all_loans: Vec::new(),
@@ -49,8 +51,12 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         move_error_collector: move_error::MoveErrorCollector::new(),
     };
 
+    let param_env = ParameterEnvironment::for_item(bccx.tcx, fn_id);
+
     {
-        let mut euv = euv::ExprUseVisitor::new(&mut glcx, bccx.tcx);
+        let mut euv = euv::ExprUseVisitor::new(&mut glcx,
+                                               bccx.tcx,
+                                               param_env);
         euv.walk_fn(decl, body);
     }
 
diff --git a/src/librustc/middle/borrowck/graphviz.rs b/src/librustc/middle/borrowck/graphviz.rs
index a209b1a28f2..32fa5f8c3a9 100644
--- a/src/librustc/middle/borrowck/graphviz.rs
+++ b/src/librustc/middle/borrowck/graphviz.rs
@@ -34,6 +34,8 @@ pub enum Variant {
     Assigns,
 }
 
+impl Copy for Variant {}
+
 impl Variant {
     pub fn short_name(&self) -> &'static str {
         match *self {
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 0bbcdfe61bb..e90de1b6912 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -25,7 +25,7 @@ use middle::dataflow::DataFlowOperator;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
 use middle::region;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, ParameterEnvironment, Ty};
 use util::ppaux::{note_and_explain_region, Repr, UserString};
 
 use std::rc::Rc;
@@ -62,6 +62,8 @@ pub mod move_data;
 #[deriving(Clone)]
 pub struct LoanDataFlowOperator;
 
+impl Copy for LoanDataFlowOperator {}
+
 pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>;
 
 impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> {
@@ -146,8 +148,13 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
     move_data::fragments::instrument_move_fragments(&flowed_moves.move_data,
                                                     this.tcx, sp, id);
 
-    check_loans::check_loans(this, &loan_dfcx, flowed_moves,
-                             all_loans.as_slice(), decl, body);
+    check_loans::check_loans(this,
+                             &loan_dfcx,
+                             flowed_moves,
+                             all_loans.as_slice(),
+                             id,
+                             decl,
+                             body);
 
     visit::walk_fn(this, fk, decl, body, sp);
 }
@@ -162,7 +169,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
     // Check the body of fn items.
     let id_range = ast_util::compute_id_range_for_fn_body(fk, decl, body, sp, id);
     let (all_loans, move_data) =
-        gather_loans::gather_loans_in_fn(this, decl, body);
+        gather_loans::gather_loans_in_fn(this, id, decl, body);
 
     let mut loan_dfcx =
         DataFlowContext::new(this.tcx,
@@ -339,6 +346,8 @@ pub enum LoanPathElem {
     LpInterior(mc::InteriorKind) // `LV.f` in doc.rs
 }
 
+impl Copy for LoanPathElem {}
+
 pub fn closure_to_block(closure_id: ast::NodeId,
                         tcx: &ty::ctxt) -> ast::NodeId {
     match tcx.map.get(closure_id) {
@@ -484,6 +493,7 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
 
 // Errors that can occur
 #[deriving(PartialEq)]
+#[allow(missing_copy_implementations)]
 pub enum bckerr_code {
     err_mutbl,
     err_out_of_scope(ty::Region, ty::Region), // superscope, subscope
@@ -505,12 +515,16 @@ pub enum AliasableViolationKind {
     BorrowViolation(euv::LoanCause)
 }
 
+impl Copy for AliasableViolationKind {}
+
 #[deriving(Show)]
 pub enum MovedValueUseKind {
     MovedInUse,
     MovedInCapture,
 }
 
+impl Copy for MovedValueUseKind {}
+
 ///////////////////////////////////////////////////////////////////////////
 // Misc
 
@@ -545,7 +559,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                      use_kind: MovedValueUseKind,
                                      lp: &LoanPath<'tcx>,
                                      the_move: &move_data::Move,
-                                     moved_lp: &LoanPath<'tcx>) {
+                                     moved_lp: &LoanPath<'tcx>,
+                                     param_env: &ParameterEnvironment<'tcx>) {
         let verb = match use_kind {
             MovedInUse => "use",
             MovedInCapture => "capture",
@@ -621,7 +636,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                                   r).as_slice())
                     }
                 };
-                let (suggestion, _) = move_suggestion(self.tcx, expr_ty,
+                let (suggestion, _) = move_suggestion(self.tcx, param_env, expr_ty,
                         ("moved by default", ""));
                 self.tcx.sess.span_note(
                     expr_span,
@@ -659,7 +674,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                                   r).as_slice())
                     }
                 };
-                let (suggestion, help) = move_suggestion(self.tcx, expr_ty,
+                let (suggestion, help) = move_suggestion(self.tcx,
+                                                         param_env,
+                                                         expr_ty,
                         ("moved by default", "make a copy and \
                          capture that instead to override"));
                 self.tcx.sess.span_note(
@@ -674,7 +691,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             }
         }
 
-        fn move_suggestion<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>,
+        fn move_suggestion<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                 param_env: &ty::ParameterEnvironment<'tcx>,
+                                 ty: Ty<'tcx>,
                                  default_msgs: (&'static str, &'static str))
                                  -> (&'static str, &'static str) {
             match ty.sty {
@@ -684,7 +703,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                     }) =>
                     ("a non-copyable stack closure",
                      "capture it in a new closure, e.g. `|x| f(x)`, to override"),
-                _ if ty::type_moves_by_default(tcx, ty) =>
+                _ if ty::type_moves_by_default(tcx, ty, param_env) =>
                     ("non-copyable",
                      "perhaps you meant to use `clone()`?"),
                 _ => default_msgs,
diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs
index 7bf3458f0ae..3bb6145c5ca 100644
--- a/src/librustc/middle/borrowck/move_data.rs
+++ b/src/librustc/middle/borrowck/move_data.rs
@@ -81,6 +81,8 @@ pub struct FlowedMoveData<'a, 'tcx: 'a> {
 #[deriving(PartialEq, Eq, PartialOrd, Ord, Show)]
 pub struct MovePathIndex(uint);
 
+impl Copy for MovePathIndex {}
+
 impl MovePathIndex {
     fn get(&self) -> uint {
         let MovePathIndex(v) = *self; v
@@ -101,6 +103,8 @@ static InvalidMovePathIndex: MovePathIndex =
 #[deriving(PartialEq)]
 pub struct MoveIndex(uint);
 
+impl Copy for MoveIndex {}
+
 impl MoveIndex {
     fn get(&self) -> uint {
         let MoveIndex(v) = *self; v
@@ -138,6 +142,8 @@ pub enum MoveKind {
     Captured    // Closure creation that moves a value
 }
 
+impl Copy for MoveKind {}
+
 pub struct Move {
     /// Path being moved.
     pub path: MovePathIndex,
@@ -152,6 +158,8 @@ pub struct Move {
     pub next_move: MoveIndex
 }
 
+impl Copy for Move {}
+
 pub struct Assignment {
     /// Path being assigned.
     pub path: MovePathIndex,
@@ -163,6 +171,8 @@ pub struct Assignment {
     pub span: Span,
 }
 
+impl Copy for Assignment {}
+
 pub struct VariantMatch {
     /// downcast to the variant.
     pub path: MovePathIndex,
@@ -177,14 +187,20 @@ pub struct VariantMatch {
     pub mode: euv::MatchMode
 }
 
+impl Copy for VariantMatch {}
+
 #[deriving(Clone)]
 pub struct MoveDataFlowOperator;
 
+impl Copy for MoveDataFlowOperator {}
+
 pub type MoveDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, MoveDataFlowOperator>;
 
 #[deriving(Clone)]
 pub struct AssignDataFlowOperator;
 
+impl Copy for AssignDataFlowOperator {}
+
 pub type AssignDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, AssignDataFlowOperator>;
 
 fn loan_path_is_precise(loan_path: &LoanPath) -> bool {
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 90919609e2e..0dcb78f6bb0 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -32,6 +32,8 @@ struct LoopScope {
     break_index: CFGIndex,    // where to go on a `break
 }
 
+impl Copy for LoopScope {}
+
 pub fn construct(tcx: &ty::ctxt,
                  blk: &ast::Block) -> CFG {
     let mut graph = graph::Graph::new();
diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs
index a2e8ba8d65c..bc512a73a4b 100644
--- a/src/librustc/middle/cfg/mod.rs
+++ b/src/librustc/middle/cfg/mod.rs
@@ -30,6 +30,8 @@ pub struct CFGNodeData {
     pub id: ast::NodeId
 }
 
+impl Copy for CFGNodeData {}
+
 pub struct CFGEdgeData {
     pub exiting_scopes: Vec<ast::NodeId>
 }
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index 36742df9850..eb073e07b02 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -21,11 +21,15 @@ enum Context {
     Normal, Loop, Closure
 }
 
+impl Copy for Context {}
+
 struct CheckLoopVisitor<'a> {
     sess: &'a Session,
     cx: Context
 }
 
+impl<'a> Copy for CheckLoopVisitor<'a> {}
+
 pub fn check_crate(sess: &Session, krate: &ast::Crate) {
     visit::walk_crate(&mut CheckLoopVisitor { sess: sess, cx: Normal }, krate)
 }
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index ed119081f78..2c437ae046b 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -99,7 +99,8 @@ impl<'a> FromIterator<Vec<&'a Pat>> for Matrix<'a> {
 }
 
 pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
-    pub tcx: &'a ty::ctxt<'tcx>
+    pub tcx: &'a ty::ctxt<'tcx>,
+    pub param_env: ParameterEnvironment<'tcx>,
 }
 
 #[deriving(Clone, PartialEq)]
@@ -131,6 +132,8 @@ enum WitnessPreference {
     LeaveOutWitness
 }
 
+impl Copy for WitnessPreference {}
+
 impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &ast::Expr) {
         check_expr(self, ex);
@@ -145,7 +148,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt) {
-    visit::walk_crate(&mut MatchCheckCtxt { tcx: tcx }, tcx.map.krate());
+    visit::walk_crate(&mut MatchCheckCtxt {
+        tcx: tcx,
+        param_env: ty::empty_parameter_environment(),
+    }, tcx.map.krate());
     tcx.sess.abort_if_errors();
 }
 
@@ -954,8 +960,14 @@ fn check_fn(cx: &mut MatchCheckCtxt,
             decl: &ast::FnDecl,
             body: &ast::Block,
             sp: Span,
-            _: NodeId) {
+            fn_id: NodeId) {
+    match kind {
+        visit::FkFnBlock => {}
+        _ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id),
+    }
+
     visit::walk_fn(cx, kind, decl, body, sp);
+
     for input in decl.inputs.iter() {
         is_refutable(cx, &*input.pat, |pat| {
             span_err!(cx.tcx.sess, input.pat.span, E0006,
@@ -1020,7 +1032,9 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                 match p.node {
                     ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
                         let pat_ty = ty::node_id_to_type(tcx, p.id);
-                        if ty::type_moves_by_default(tcx, pat_ty) {
+                        if ty::type_moves_by_default(tcx,
+                                                      pat_ty,
+                                                      &cx.param_env) {
                             check_move(p, sub.as_ref().map(|p| &**p));
                         }
                     }
@@ -1048,7 +1062,9 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>,
     let mut checker = MutationChecker {
         cx: cx,
     };
-    let mut visitor = ExprUseVisitor::new(&mut checker, checker.cx.tcx);
+    let mut visitor = ExprUseVisitor::new(&mut checker,
+                                          checker.cx.tcx,
+                                          cx.param_env.clone());
     visitor.walk_expr(guard);
 }
 
diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs
index dae76ba125e..a14307b90ee 100644
--- a/src/librustc/middle/check_rvalues.rs
+++ b/src/librustc/middle/check_rvalues.rs
@@ -13,6 +13,7 @@
 
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
+use middle::ty::ParameterEnvironment;
 use middle::ty;
 use util::ppaux::ty_to_string;
 
@@ -36,9 +37,10 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> {
                 fd: &'v ast::FnDecl,
                 b: &'v ast::Block,
                 s: Span,
-                _: ast::NodeId) {
+                fn_id: ast::NodeId) {
         {
-            let mut euv = euv::ExprUseVisitor::new(self, self.tcx);
+            let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
+            let mut euv = euv::ExprUseVisitor::new(self, self.tcx, param_env);
             euv.walk_fn(fd, b);
         }
         visit::walk_fn(self, fk, fd, b, s)
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index 2fc85afd393..a495d1e049d 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -47,13 +47,16 @@ enum Mode {
     InNothing,
 }
 
+impl Copy for Mode {}
+
 struct CheckStaticVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     mode: Mode,
     checker: &'a mut GlobalChecker,
 }
 
-struct GlobalVisitor<'a, 'b, 'tcx: 'b>(euv::ExprUseVisitor<'a, 'b, 'tcx, ty::ctxt<'tcx>>);
+struct GlobalVisitor<'a,'b,'tcx:'a+'b>(
+    euv::ExprUseVisitor<'a,'b,'tcx,ty::ctxt<'tcx>>);
 struct GlobalChecker {
     static_consumptions: NodeSet,
     const_borrows: NodeSet,
@@ -69,7 +72,8 @@ pub fn check_crate(tcx: &ty::ctxt) {
         static_local_borrows: NodeSet::new(),
     };
     {
-        let visitor = euv::ExprUseVisitor::new(&mut checker, tcx);
+        let param_env = ty::empty_parameter_environment();
+        let visitor = euv::ExprUseVisitor::new(&mut checker, tcx, param_env);
         visit::walk_crate(&mut GlobalVisitor(visitor), tcx.map.krate());
     }
     visit::walk_crate(&mut CheckStaticVisitor {
@@ -242,7 +246,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> {
     }
 }
 
-impl<'a, 'b, 't, 'v> Visitor<'v> for GlobalVisitor<'a, 'b, 't> {
+impl<'a,'b,'t,'v> Visitor<'v> for GlobalVisitor<'a,'b,'t> {
     fn visit_item(&mut self, item: &ast::Item) {
         match item.node {
             ast::ItemConst(_, ref e) |
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 43726f55bb9..150bcbdd688 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -68,6 +68,8 @@ pub enum constness {
     non_const
 }
 
+impl Copy for constness {}
+
 type constness_cache = DefIdMap<constness>;
 
 pub fn join(a: constness, b: constness) -> constness {
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 53fea8ffc86..db8fd999f38 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -28,7 +28,12 @@ use syntax::print::{pp, pprust};
 use util::nodemap::NodeMap;
 
 #[deriving(Show)]
-pub enum EntryOrExit { Entry, Exit }
+pub enum EntryOrExit {
+    Entry,
+    Exit,
+}
+
+impl Copy for EntryOrExit {}
 
 #[deriving(Clone)]
 pub struct DataFlowContext<'a, 'tcx: 'a, O> {
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index 4a4298f62f2..b3e4dd25adc 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -52,6 +52,8 @@ pub enum Def {
     DefMethod(ast::DefId /* method */, Option<ast::DefId> /* trait */, MethodProvenance),
 }
 
+impl Copy for Def {}
+
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum MethodProvenance {
     FromTrait(ast::DefId),
@@ -67,6 +69,8 @@ impl MethodProvenance {
     }
 }
 
+impl Copy for MethodProvenance {}
+
 impl Def {
     pub fn def_id(&self) -> ast::DefId {
         match *self {
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index dbec69f4205..8bf43c70c26 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -30,6 +30,8 @@ enum UnsafeContext {
     UnsafeBlock(ast::NodeId),
 }
 
+impl Copy for UnsafeContext {}
+
 fn type_is_unsafe_function(ty: Ty) -> bool {
     match ty.sty {
         ty::ty_bare_fn(ref f) => f.fn_style == ast::UnsafeFn,
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 7d2bb7458ac..8e00c96535b 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -23,12 +23,13 @@ use self::OverloadedCallType::*;
 use middle::{def, region, pat_util};
 use middle::mem_categorization as mc;
 use middle::mem_categorization::Typer;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, ParameterEnvironment, Ty};
 use middle::ty::{MethodCall, MethodObject, MethodTraitObject};
 use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam};
 use middle::ty::{MethodStatic, MethodStaticUnboxedClosure};
 use util::ppaux::Repr;
 
+use std::kinds;
 use syntax::ast;
 use syntax::ptr::P;
 use syntax::codemap::Span;
@@ -106,12 +107,16 @@ pub enum LoanCause {
     MatchDiscriminant
 }
 
+impl kinds::Copy for LoanCause {}
+
 #[deriving(PartialEq, Show)]
 pub enum ConsumeMode {
     Copy,                // reference to x where x has a type that copies
     Move(MoveReason),    // reference to x where x has a type that moves
 }
 
+impl kinds::Copy for ConsumeMode {}
+
 #[deriving(PartialEq,Show)]
 pub enum MoveReason {
     DirectRefMove,
@@ -119,6 +124,8 @@ pub enum MoveReason {
     CaptureMove,
 }
 
+impl kinds::Copy for MoveReason {}
+
 #[deriving(PartialEq,Show)]
 pub enum MatchMode {
     NonBindingMatch,
@@ -127,11 +134,17 @@ pub enum MatchMode {
     MovingMatch,
 }
 
+impl kinds::Copy for MatchMode {}
+
 #[deriving(PartialEq,Show)]
 enum TrackMatchMode<T> {
-    Unknown, Definite(MatchMode), Conflicting,
+    Unknown,
+    Definite(MatchMode),
+    Conflicting,
 }
 
+impl<T> kinds::Copy for TrackMatchMode<T> {}
+
 impl<T> TrackMatchMode<T> {
     // Builds up the whole match mode for a pattern from its constituent
     // parts.  The lattice looks like this:
@@ -199,12 +212,16 @@ pub enum MutateMode {
     WriteAndRead, // x += y
 }
 
+impl kinds::Copy for MutateMode {}
+
 enum OverloadedCallType {
     FnOverloadedCall,
     FnMutOverloadedCall,
     FnOnceOverloadedCall,
 }
 
+impl kinds::Copy for OverloadedCallType {}
+
 impl OverloadedCallType {
     fn from_trait_id(tcx: &ty::ctxt, trait_id: ast::DefId)
                      -> OverloadedCallType {
@@ -293,6 +310,7 @@ pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> {
     typer: &'t TYPER,
     mc: mc::MemCategorizationContext<'t,TYPER>,
     delegate: &'d mut (Delegate<'tcx>+'d),
+    param_env: ParameterEnvironment<'tcx>,
 }
 
 // If the TYPER results in an error, it's because the type check
@@ -313,11 +331,15 @@ macro_rules! return_if_err(
 
 impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     pub fn new(delegate: &'d mut Delegate<'tcx>,
-               typer: &'t TYPER)
+               typer: &'t TYPER,
+               param_env: ParameterEnvironment<'tcx>)
                -> ExprUseVisitor<'d,'t,'tcx,TYPER> {
-        ExprUseVisitor { typer: typer,
-                         mc: mc::MemCategorizationContext::new(typer),
-                         delegate: delegate }
+        ExprUseVisitor {
+            typer: typer,
+            mc: mc::MemCategorizationContext::new(typer),
+            delegate: delegate,
+            param_env: param_env,
+        }
     }
 
     pub fn walk_fn(&mut self,
@@ -352,7 +374,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         consume_id: ast::NodeId,
                         consume_span: Span,
                         cmt: mc::cmt<'tcx>) {
-        let mode = copy_or_move(self.tcx(), cmt.ty, DirectRefMove);
+        let mode = copy_or_move(self.tcx(),
+                                cmt.ty,
+                                &self.param_env,
+                                DirectRefMove);
         self.delegate.consume(consume_id, consume_span, cmt, mode);
     }
 
@@ -954,7 +979,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                     ast::PatIdent(ast::BindByRef(_), _, _) =>
                         mode.lub(BorrowingMatch),
                     ast::PatIdent(ast::BindByValue(_), _, _) => {
-                        match copy_or_move(tcx, cmt_pat.ty, PatBindingMove) {
+                        match copy_or_move(tcx,
+                                           cmt_pat.ty,
+                                           &self.param_env,
+                                           PatBindingMove) {
                             Copy => mode.lub(CopyingMatch),
                             Move(_) => mode.lub(MovingMatch),
                         }
@@ -984,7 +1012,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
         let tcx = typer.tcx();
         let def_map = &self.typer.tcx().def_map;
         let delegate = &mut self.delegate;
-
+        let param_env = &mut self.param_env;
         return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
             if pat_util::pat_is_binding(def_map, pat) {
                 let tcx = typer.tcx();
@@ -1018,7 +1046,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                                              r, bk, RefBinding);
                     }
                     ast::PatIdent(ast::BindByValue(_), _, _) => {
-                        let mode = copy_or_move(typer.tcx(), cmt_pat.ty, PatBindingMove);
+                        let mode = copy_or_move(typer.tcx(),
+                                                cmt_pat.ty,
+                                                param_env,
+                                                PatBindingMove);
                         debug!("walk_pat binding consuming pat");
                         delegate.consume_pat(pat, cmt_pat, mode);
                     }
@@ -1211,7 +1242,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
                                                                closure_expr.span,
                                                                freevar.def));
-            let mode = copy_or_move(self.tcx(), cmt_var.ty, CaptureMove);
+            let mode = copy_or_move(self.tcx(),
+                                    cmt_var.ty,
+                                    &self.param_env,
+                                    CaptureMove);
             self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
         }
     }
@@ -1229,8 +1263,15 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     }
 }
 
-fn copy_or_move<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>,
-                      move_reason: MoveReason) -> ConsumeMode {
-    if ty::type_moves_by_default(tcx, ty) { Move(move_reason) } else { Copy }
+fn copy_or_move<'tcx>(tcx: &ty::ctxt<'tcx>,
+                      ty: Ty<'tcx>,
+                      param_env: &ParameterEnvironment<'tcx>,
+                      move_reason: MoveReason)
+                      -> ConsumeMode {
+    if ty::type_moves_by_default(tcx, ty, param_env) {
+        Move(move_reason)
+    } else {
+        Copy
+    }
 }
 
diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs
index 888f01f9118..6780177933f 100644
--- a/src/librustc/middle/fast_reject.rs
+++ b/src/librustc/middle/fast_reject.rs
@@ -33,6 +33,8 @@ pub enum SimplifiedType {
     ParameterSimplifiedType,
 }
 
+impl Copy for SimplifiedType {}
+
 /// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc.
 /// The idea is to get something simple that we can use to quickly decide if two types could unify
 /// during method lookup.
diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs
index 2f50a964023..e45232a3c30 100644
--- a/src/librustc/middle/graph.rs
+++ b/src/librustc/middle/graph.rs
@@ -65,11 +65,15 @@ pub struct NodeIndex(pub uint);
 #[allow(non_upper_case_globals)]
 pub const InvalidNodeIndex: NodeIndex = NodeIndex(uint::MAX);
 
+impl Copy for NodeIndex {}
+
 #[deriving(PartialEq, Show)]
 pub struct EdgeIndex(pub uint);
 #[allow(non_upper_case_globals)]
 pub const InvalidEdgeIndex: EdgeIndex = EdgeIndex(uint::MAX);
 
+impl Copy for EdgeIndex {}
+
 // Use a private field here to guarantee no more instances are created:
 #[deriving(Show)]
 pub struct Direction { repr: uint }
@@ -78,6 +82,8 @@ pub const Outgoing: Direction = Direction { repr: 0 };
 #[allow(non_upper_case_globals)]
 pub const Incoming: Direction = Direction { repr: 1 };
 
+impl Copy for Direction {}
+
 impl NodeIndex {
     fn get(&self) -> uint { let NodeIndex(v) = *self; v }
     /// Returns unique id (unique with respect to the graph holding associated node).
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index c5845b143af..81cd8dd20d2 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -132,6 +132,8 @@ pub enum TypeOrigin {
     IfExpressionWithNoElse(Span)
 }
 
+impl Copy for TypeOrigin {}
+
 /// See `error_reporting.rs` for more details
 #[deriving(Clone, Show)]
 pub enum ValuePairs<'tcx> {
@@ -237,6 +239,8 @@ pub enum LateBoundRegionConversionTime {
     HigherRankedType,
 }
 
+impl Copy for LateBoundRegionConversionTime {}
+
 /// Reasons to create a region inference variable
 ///
 /// See `error_reporting.rs` for more details
@@ -280,6 +284,8 @@ pub enum fixup_err {
     unresolved_ty(TyVid)
 }
 
+impl Copy for fixup_err {}
+
 pub fn fixup_err_to_string(f: fixup_err) -> String {
     match f {
       unresolved_int_ty(_) => {
diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs
index 9155c18cb3b..391e37e8b9c 100644
--- a/src/librustc/middle/infer/region_inference/mod.rs
+++ b/src/librustc/middle/infer/region_inference/mod.rs
@@ -51,6 +51,8 @@ pub enum Constraint {
     ConstrainVarSubReg(RegionVid, Region),
 }
 
+impl Copy for Constraint {}
+
 // Something we have to verify after region inference is done, but
 // which does not directly influence the inference process
 pub enum Verify<'tcx> {
@@ -72,6 +74,8 @@ pub struct TwoRegions {
     b: Region,
 }
 
+impl Copy for TwoRegions {}
+
 #[deriving(PartialEq)]
 pub enum UndoLogEntry {
     OpenSnapshot,
@@ -84,11 +88,15 @@ pub enum UndoLogEntry {
     AddCombination(CombineMapType, TwoRegions)
 }
 
+impl Copy for UndoLogEntry {}
+
 #[deriving(PartialEq)]
 pub enum CombineMapType {
     Lub, Glb
 }
 
+impl Copy for CombineMapType {}
+
 #[deriving(Clone, Show)]
 pub enum RegionResolutionError<'tcx> {
     /// `ConcreteFailure(o, a, b)`:
@@ -220,11 +228,15 @@ pub struct RegionSnapshot {
     length: uint
 }
 
+impl Copy for RegionSnapshot {}
+
 #[deriving(Show)]
 pub struct RegionMark {
     length: uint
 }
 
+impl Copy for RegionMark {}
+
 impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
     pub fn new(tcx: &'a ty::ctxt<'tcx>) -> RegionVarBindings<'a, 'tcx> {
         RegionVarBindings {
@@ -926,8 +938,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
 #[deriving(PartialEq, Show)]
 enum Classification { Expanding, Contracting }
 
+impl Copy for Classification {}
+
 pub enum VarValue { NoValue, Value(Region), ErrorValue }
 
+impl Copy for VarValue {}
+
 struct VarData {
     classification: Classification,
     value: VarValue,
diff --git a/src/librustc/middle/infer/type_variable.rs b/src/librustc/middle/infer/type_variable.rs
index 3058f09a83a..766e930486c 100644
--- a/src/librustc/middle/infer/type_variable.rs
+++ b/src/librustc/middle/infer/type_variable.rs
@@ -49,6 +49,8 @@ pub enum RelationDir {
     SubtypeOf, SupertypeOf, EqTo
 }
 
+impl Copy for RelationDir {}
+
 impl RelationDir {
     fn opposite(self) -> RelationDir {
         match self {
diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs
index 6f6adb84a75..a2dd4d62913 100644
--- a/src/librustc/middle/infer/unify.rs
+++ b/src/librustc/middle/infer/unify.rs
@@ -92,6 +92,8 @@ pub struct Node<K,V> {
 
 pub struct Delegate;
 
+impl Copy for Delegate {}
+
 // We can't use V:LatticeValue, much as I would like to,
 // because frequently the pattern is that V=Option<U> for some
 // other type parameter U, and we have no way to say
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index da1c0bd649a..4a20c92d8e2 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -50,6 +50,8 @@ pub enum LangItem {
     $($variant),*
 }
 
+impl Copy for LangItem {}
+
 pub struct LanguageItems {
     pub items: Vec<Option<ast::DefId>>,
     pub missing: Vec<LangItem>,
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index a6d3c15df8a..5edbafc4e0b 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -137,9 +137,14 @@ enum LoopKind<'a> {
 
 #[deriving(PartialEq)]
 struct Variable(uint);
+
+impl Copy for Variable {}
+
 #[deriving(PartialEq)]
 struct LiveNode(uint);
 
+impl Copy for LiveNode {}
+
 impl Variable {
     fn get(&self) -> uint { let Variable(v) = *self; v }
 }
@@ -162,6 +167,8 @@ enum LiveNodeKind {
     ExitNode
 }
 
+impl Copy for LiveNodeKind {}
+
 fn live_node_kind_to_string(lnk: LiveNodeKind, cx: &ty::ctxt) -> String {
     let cm = cx.sess.codemap();
     match lnk {
@@ -246,6 +253,8 @@ struct LocalInfo {
     ident: ast::Ident
 }
 
+impl Copy for LocalInfo {}
+
 #[deriving(Show)]
 enum VarKind {
     Arg(NodeId, ast::Ident),
@@ -254,6 +263,8 @@ enum VarKind {
     CleanExit
 }
 
+impl Copy for VarKind {}
+
 struct IrMaps<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
 
@@ -532,6 +543,8 @@ struct Users {
     used: bool
 }
 
+impl Copy for Users {}
+
 fn invalid_users() -> Users {
     Users {
         reader: invalid_node(),
@@ -547,6 +560,8 @@ struct Specials {
     clean_exit_var: Variable
 }
 
+impl Copy for Specials {}
+
 static ACC_READ: uint = 1u;
 static ACC_WRITE: uint = 2u;
 static ACC_USE: uint = 4u;
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index cd70d8e2b48..302fbd53dd5 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -110,6 +110,8 @@ pub struct Upvar {
     pub is_unboxed: bool
 }
 
+impl Copy for Upvar {}
+
 // different kinds of pointers:
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub enum PointerKind {
@@ -119,6 +121,8 @@ pub enum PointerKind {
     UnsafePtr(ast::Mutability)
 }
 
+impl Copy for PointerKind {}
+
 // We use the term "interior" to mean "something reachable from the
 // base without a pointer dereference", e.g. a field
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
@@ -127,18 +131,24 @@ pub enum InteriorKind {
     InteriorElement(ElementKind),
 }
 
+impl Copy for InteriorKind {}
+
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub enum FieldName {
     NamedField(ast::Name),
     PositionalField(uint)
 }
 
+impl Copy for FieldName {}
+
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub enum ElementKind {
     VecElement,
     OtherElement,
 }
 
+impl Copy for ElementKind {}
+
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub enum MutabilityCategory {
     McImmutable, // Immutable.
@@ -146,6 +156,8 @@ pub enum MutabilityCategory {
     McInherited, // Inherited from the fact that owner is mutable.
 }
 
+impl Copy for MutabilityCategory {}
+
 // A note about the provenance of a `cmt`.  This is used for
 // special-case handling of upvars such as mutability inference.
 // Upvar categorization can generate a variable number of nested
@@ -158,6 +170,8 @@ pub enum Note {
     NoteNone                     // Nothing special
 }
 
+impl Copy for Note {}
+
 // `cmt`: "Category, Mutability, and Type".
 //
 // a complete categorization of a value indicating where it originated
@@ -191,6 +205,8 @@ pub enum deref_kind {
     deref_interior(InteriorKind),
 }
 
+impl Copy for deref_kind {}
+
 // Categorizes a derefable type.  Note that we include vectors and strings as
 // derefable (we model an index as the combination of a deref and then a
 // pointer adjustment).
@@ -261,6 +277,8 @@ pub struct MemCategorizationContext<'t,TYPER:'t> {
     typer: &'t TYPER
 }
 
+impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
+
 pub type McResult<T> = Result<T, ()>;
 
 /// The `Typer` trait provides the interface for the mem-categorization
@@ -1384,6 +1402,8 @@ pub enum InteriorSafety {
     InteriorSafe
 }
 
+impl Copy for InteriorSafety {}
+
 pub enum AliasableReason {
     AliasableBorrowed,
     AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env
@@ -1392,6 +1412,8 @@ pub enum AliasableReason {
     AliasableStaticMut(InteriorSafety),
 }
 
+impl Copy for AliasableReason {}
+
 impl<'tcx> cmt_<'tcx> {
     pub fn guarantor(&self) -> cmt<'tcx> {
         //! Returns `self` after stripping away any owned pointer derefs or
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 2b8dd8df249..370097004e9 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -41,6 +41,8 @@ pub enum CodeExtent {
     Misc(ast::NodeId)
 }
 
+impl Copy for CodeExtent {}
+
 impl CodeExtent {
     /// Creates a scope that represents the dynamic extent associated
     /// with `node_id`.
@@ -120,6 +122,8 @@ pub struct Context {
     parent: Option<ast::NodeId>,
 }
 
+impl Copy for Context {}
+
 struct RegionResolutionVisitor<'a> {
     sess: &'a Session,
 
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 8c3aa22c5fc..36b87bbd423 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -94,6 +94,8 @@ struct binding_info {
     binding_mode: BindingMode,
 }
 
+impl Copy for binding_info {}
+
 // Map from the name in a pattern to its binding mode.
 type BindingMap = HashMap<Name,binding_info>;
 
@@ -130,12 +132,16 @@ pub enum LastPrivate {
                type_used: ImportUse},
 }
 
+impl Copy for LastPrivate {}
+
 #[deriving(Show)]
 pub enum PrivateDep {
     AllPublic,
     DependsOn(DefId),
 }
 
+impl Copy for PrivateDep {}
+
 // How an import is used.
 #[deriving(PartialEq, Show)]
 pub enum ImportUse {
@@ -143,6 +149,8 @@ pub enum ImportUse {
     Used,         // The import is used.
 }
 
+impl Copy for ImportUse {}
+
 impl LastPrivate {
     fn or(self, other: LastPrivate) -> LastPrivate {
         match (self, other) {
@@ -159,12 +167,16 @@ enum PatternBindingMode {
     ArgumentIrrefutableMode,
 }
 
+impl Copy for PatternBindingMode {}
+
 #[deriving(PartialEq, Eq, Hash, Show)]
 enum Namespace {
     TypeNS,
     ValueNS
 }
 
+impl Copy for Namespace {}
+
 #[deriving(PartialEq)]
 enum NamespaceError {
     NoError,
@@ -173,6 +185,8 @@ enum NamespaceError {
     ValueError
 }
 
+impl Copy for NamespaceError {}
+
 /// A NamespaceResult represents the result of resolving an import in
 /// a particular namespace. The result is either definitely-resolved,
 /// definitely- unresolved, or unknown.
@@ -238,6 +252,8 @@ enum ImportDirectiveSubclass {
     GlobImport
 }
 
+impl Copy for ImportDirectiveSubclass {}
+
 /// The context that we thread through while building the reduced graph.
 #[deriving(Clone)]
 enum ReducedGraphParent {
@@ -294,6 +310,8 @@ enum TypeParameters<'a> {
         RibKind)
 }
 
+impl<'a> Copy for TypeParameters<'a> {}
+
 // The rib kind controls the translation of local
 // definitions (`DefLocal`) to upvars (`DefUpvar`).
 
@@ -319,17 +337,23 @@ enum RibKind {
     ConstantItemRibKind
 }
 
+impl Copy for RibKind {}
+
 // Methods can be required or provided. RequiredMethod methods only occur in traits.
 enum MethodSort {
     RequiredMethod,
     ProvidedMethod(NodeId)
 }
 
+impl Copy for MethodSort {}
+
 enum UseLexicalScopeFlag {
     DontUseLexicalScope,
     UseLexicalScope
 }
 
+impl Copy for UseLexicalScopeFlag {}
+
 enum ModulePrefixResult {
     NoPrefixFound,
     PrefixFound(Rc<Module>, uint)
@@ -342,6 +366,8 @@ pub enum TraitItemKind {
     TypeTraitItemKind,
 }
 
+impl Copy for TraitItemKind {}
+
 impl TraitItemKind {
     pub fn from_explicit_self_category(explicit_self_category:
                                        ExplicitSelfCategory)
@@ -364,12 +390,16 @@ enum NameSearchType {
     PathSearch,
 }
 
+impl Copy for NameSearchType {}
+
 enum BareIdentifierPatternResolution {
     FoundStructOrEnumVariant(Def, LastPrivate),
     FoundConst(Def, LastPrivate),
     BareIdentifierPatternUnresolved
 }
 
+impl Copy for BareIdentifierPatternResolution {}
+
 // Specifies how duplicates should be handled when adding a child item if
 // another item exists with the same name in some namespace.
 #[deriving(PartialEq)]
@@ -381,6 +411,8 @@ enum DuplicateCheckingMode {
     OverwriteDuplicates
 }
 
+impl Copy for DuplicateCheckingMode {}
+
 /// One local scope.
 struct Rib {
     bindings: HashMap<Name, DefLike>,
@@ -518,6 +550,8 @@ enum ModuleKind {
     AnonymousModuleKind,
 }
 
+impl Copy for ModuleKind {}
+
 /// One node in the tree of modules.
 struct Module {
     parent_link: ParentLink,
@@ -599,6 +633,8 @@ bitflags! {
     }
 }
 
+impl Copy for DefModifiers {}
+
 // Records a possibly-private type definition.
 #[deriving(Clone)]
 struct TypeNsDef {
@@ -616,6 +652,8 @@ struct ValueNsDef {
     value_span: Option<Span>,
 }
 
+impl Copy for ValueNsDef {}
+
 // Records the definitions (at most one for each namespace) that a name is
 // bound to.
 struct NameBindings {
@@ -632,6 +670,8 @@ enum TraitReferenceType {
     TraitQPath,                      // <T as SomeTrait>::
 }
 
+impl Copy for TraitReferenceType {}
+
 impl NameBindings {
     fn new() -> NameBindings {
         NameBindings {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index bd8db1d51df..2ba9ba5631d 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -46,6 +46,8 @@ pub enum DefRegion {
                   /* lifetime decl */ ast::NodeId),
 }
 
+impl Copy for DefRegion {}
+
 // maps the id of each lifetime reference to the lifetime decl
 // that it corresponds to
 pub type NamedRegionMap = NodeMap<DefRegion>;
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index 21f57a9d573..bcc762a9640 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -190,6 +190,8 @@ pub enum ParamSpace {
     FnSpace,    // Type parameters attached to a method or fn
 }
 
+impl Copy for ParamSpace {}
+
 impl ParamSpace {
     pub fn all() -> [ParamSpace, ..4] {
         [TypeSpace, SelfSpace, AssocSpace, FnSpace]
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index e12ec44ad87..d410a456dc9 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -60,6 +60,8 @@ pub struct ObligationCause<'tcx> {
     pub code: ObligationCauseCode<'tcx>
 }
 
+impl<'tcx> Copy for ObligationCause<'tcx> {}
+
 #[deriving(Clone)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from span.
@@ -95,6 +97,8 @@ pub enum ObligationCauseCode<'tcx> {
 
 pub type Obligations<'tcx> = subst::VecPerParamSpace<Obligation<'tcx>>;
 
+impl<'tcx> Copy for ObligationCauseCode<'tcx> {}
+
 pub type Selection<'tcx> = Vtable<'tcx, Obligation<'tcx>>;
 
 #[deriving(Clone,Show)]
@@ -338,7 +342,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
             VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()),
             VtableParam(ref p) => VtableParam((*p).clone()),
-            VtableBuiltin(ref i) => VtableBuiltin(i.map_nested(op)),
+            VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)),
         }
     }
 
@@ -348,7 +352,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableFnPointer(sig) => VtableFnPointer(sig),
             VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s),
             VtableParam(p) => VtableParam(p),
-            VtableBuiltin(i) => VtableBuiltin(i.map_move_nested(op)),
+            VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
         }
     }
 }
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 0e6a0c19f70..5ad0d17ad13 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -80,6 +80,7 @@ struct ObligationStack<'prev, 'tcx: 'prev> {
     previous: Option<&'prev ObligationStack<'prev, 'tcx>>
 }
 
+#[deriving(Clone)]
 pub struct SelectionCache<'tcx> {
     hashmap: RefCell<HashMap<Rc<ty::TraitRef<'tcx>>,
                              SelectionResult<'tcx, Candidate<'tcx>>>>,
@@ -102,6 +103,8 @@ pub enum MethodMatchedData {
     CoerciveMethodMatch(/* impl we matched */ ast::DefId)
 }
 
+impl Copy for MethodMatchedData {}
+
 /// The selection process begins by considering all impls, where
 /// clauses, and so forth that might resolve an obligation.  Sometimes
 /// we'll be able to say definitively that (e.g.) an impl does not
@@ -918,20 +921,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // and applicable impls. There is a certain set of precedence rules here.
 
         match self.tcx().lang_items.to_builtin_kind(obligation.trait_ref.def_id) {
-            Some(bound) => {
-                try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
+            Some(ty::BoundCopy) => {
+                debug!("obligation self ty is {}",
+                       obligation.self_ty().repr(self.tcx()));
+                try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
+                try!(self.assemble_builtin_bound_candidates(ty::BoundCopy,
+                                                            stack,
+                                                            &mut candidates));
             }
 
             None => {
-                // For the time being, we ignore user-defined impls for builtin-bounds.
+                // For the time being, we ignore user-defined impls for builtin-bounds, other than
+                // `Copy`.
                 // (And unboxed candidates only apply to the Fn/FnMut/etc traits.)
                 try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates));
                 try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
                 try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
             }
+
+            Some(bound) => {
+                try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
+            }
         }
 
         try!(self.assemble_candidates_from_caller_bounds(obligation, &mut candidates));
+        debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
     }
 
@@ -1519,13 +1533,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
 
                 ty::BoundCopy => {
-                    if
-                        Some(def_id) == tcx.lang_items.no_copy_bound() ||
-                        Some(def_id) == tcx.lang_items.managed_bound() ||
-                        ty::has_dtor(tcx, def_id)
-                    {
-                        return Err(Unimplemented);
-                    }
+                    // This is an Opt-In Built-In Trait.
+                    return Ok(ParameterBuiltin)
                 }
 
                 ty::BoundSync => {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 8a2529701bb..4c4b5d07f50 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -38,6 +38,7 @@ pub use self::IntVarValue::*;
 pub use self::ExprAdjustment::*;
 pub use self::vtable_origin::*;
 pub use self::MethodOrigin::*;
+pub use self::CopyImplementationError::*;
 
 use back::svh::Svh;
 use session::Session;
@@ -52,8 +53,10 @@ use middle::mem_categorization as mc;
 use middle::region;
 use middle::resolve;
 use middle::resolve_lifetime;
+use middle::infer;
 use middle::stability;
 use middle::subst::{mod, Subst, Substs, VecPerParamSpace};
+use middle::traits::ObligationCause;
 use middle::traits;
 use middle::ty;
 use middle::ty_fold::{mod, TypeFoldable, TypeFolder, HigherRankedFoldable};
@@ -72,7 +75,7 @@ use std::hash::{Hash, sip, Writer};
 use std::mem;
 use std::ops;
 use std::rc::Rc;
-use std::collections::hash_map::{Occupied, Vacant};
+use std::collections::hash_map::{HashMap, Occupied, Vacant};
 use arena::TypedArena;
 use syntax::abi;
 use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE};
@@ -81,7 +84,7 @@ use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
 use syntax::ast::{Visibility};
 use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod};
 use syntax::attr::{mod, AttrMetaMethods};
-use syntax::codemap::Span;
+use syntax::codemap::{DUMMY_SP, Span};
 use syntax::parse::token::{mod, InternedString};
 use syntax::{ast, ast_map};
 use std::collections::enum_set::{EnumSet, CLike};
@@ -109,12 +112,16 @@ pub struct field<'tcx> {
     pub mt: mt<'tcx>
 }
 
+impl<'tcx> Copy for field<'tcx> {}
+
 #[deriving(Clone, Show)]
 pub enum ImplOrTraitItemContainer {
     TraitContainer(ast::DefId),
     ImplContainer(ast::DefId),
 }
 
+impl Copy for ImplOrTraitItemContainer {}
+
 impl ImplOrTraitItemContainer {
     pub fn id(&self) -> ast::DefId {
         match *self {
@@ -175,6 +182,8 @@ pub enum ImplOrTraitItemId {
     TypeTraitItemId(ast::DefId),
 }
 
+impl Copy for ImplOrTraitItemId {}
+
 impl ImplOrTraitItemId {
     pub fn def_id(&self) -> ast::DefId {
         match *self {
@@ -236,12 +245,16 @@ pub struct AssociatedType {
     pub container: ImplOrTraitItemContainer,
 }
 
+impl Copy for AssociatedType {}
+
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct mt<'tcx> {
     pub ty: Ty<'tcx>,
     pub mutbl: ast::Mutability,
 }
 
+impl<'tcx> Copy for mt<'tcx> {}
+
 #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
 pub enum TraitStore {
     /// Box<Trait>
@@ -250,6 +263,8 @@ pub enum TraitStore {
     RegionTraitStore(Region, ast::Mutability),
 }
 
+impl Copy for TraitStore {}
+
 #[deriving(Clone, Show)]
 pub struct field_ty {
     pub name: Name,
@@ -258,6 +273,8 @@ pub struct field_ty {
     pub origin: ast::DefId,  // The DefId of the struct in which the field is declared.
 }
 
+impl Copy for field_ty {}
+
 // Contains information needed to resolve types and (in the future) look up
 // the types of AST nodes.
 #[deriving(PartialEq, Eq, Hash)]
@@ -267,11 +284,15 @@ pub struct creader_cache_key {
     pub len: uint
 }
 
+impl Copy for creader_cache_key {}
+
 pub enum ast_ty_to_ty_cache_entry<'tcx> {
     atttce_unresolved,  /* not resolved yet */
     atttce_resolved(Ty<'tcx>)  /* resolved to a type, irrespective of region */
 }
 
+impl<'tcx> Copy for ast_ty_to_ty_cache_entry<'tcx> {}
+
 #[deriving(Clone, PartialEq, Decodable, Encodable)]
 pub struct ItemVariances {
     pub types: VecPerParamSpace<Variance>,
@@ -286,6 +307,8 @@ pub enum Variance {
     Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
 }
 
+impl Copy for Variance {}
+
 #[deriving(Clone, Show)]
 pub enum AutoAdjustment<'tcx> {
     AdjustAddEnv(ty::TraitStore),
@@ -431,6 +454,8 @@ pub struct param_index {
     pub index: uint
 }
 
+impl Copy for param_index {}
+
 #[deriving(Clone, Show)]
 pub enum MethodOrigin<'tcx> {
     // fully statically resolved method
@@ -485,6 +510,8 @@ pub struct MethodCallee<'tcx> {
     pub substs: subst::Substs<'tcx>
 }
 
+impl Copy for MethodCall {}
+
 /// With method calls, we store some extra information in
 /// side tables (i.e method_map). We use
 /// MethodCall as a key to index into these tables instead of
@@ -510,6 +537,8 @@ pub enum ExprAdjustment {
     AutoObject
 }
 
+impl Copy for ExprAdjustment {}
+
 impl MethodCall {
     pub fn expr(id: ast::NodeId) -> MethodCall {
         MethodCall {
@@ -594,6 +623,8 @@ pub struct TransmuteRestriction<'tcx> {
     pub id: ast::NodeId,
 }
 
+impl<'tcx> Copy for TransmuteRestriction<'tcx> {}
+
 /// The data structure to keep track of all the information that typechecker
 /// generates so that so that it can be reused and doesn't have to be redone
 /// later on.
@@ -746,6 +777,9 @@ pub struct ctxt<'tcx> {
 
     /// Caches the representation hints for struct definitions.
     pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
+
+    /// Caches whether types move by default.
+    pub type_moves_by_default_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
 }
 
 // Flags that we track on types. These flags are propagated upwards
@@ -766,6 +800,8 @@ bitflags! {
     }
 }
 
+impl Copy for TypeFlags {}
+
 #[deriving(Show)]
 pub struct TyS<'tcx> {
     pub sty: sty<'tcx>,
@@ -807,6 +843,7 @@ impl<'tcx> PartialEq for InternedTy<'tcx> {
         self.ty.sty == other.ty.sty
     }
 }
+
 impl<'tcx> Eq for InternedTy<'tcx> {}
 
 impl<'tcx, S: Writer> Hash<S> for InternedTy<'tcx> {
@@ -900,6 +937,8 @@ impl<'tcx> FnOutput<'tcx> {
     }
 }
 
+impl<'tcx> Copy for FnOutput<'tcx> {}
+
 /// Signature of a function type, which I have arbitrarily
 /// decided to use to refer to the input/output types.
 ///
@@ -924,6 +963,8 @@ pub struct ParamTy {
     pub def_id: DefId
 }
 
+impl Copy for ParamTy {}
+
 /// A [De Bruijn index][dbi] is a standard means of representing
 /// regions (and perhaps later types) in a higher-ranked setting. In
 /// particular, imagine a type like this:
@@ -1018,6 +1059,8 @@ pub struct UpvarId {
     pub closure_expr_id: ast::NodeId,
 }
 
+impl Copy for UpvarId {}
+
 #[deriving(Clone, PartialEq, Eq, Hash, Show, Encodable, Decodable)]
 pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
@@ -1064,6 +1107,8 @@ pub enum BorrowKind {
     MutBorrow
 }
 
+impl Copy for BorrowKind {}
+
 /// Information describing the borrowing of an upvar. This is computed
 /// during `typeck`, specifically by `regionck`. The general idea is
 /// that the compiler analyses treat closures like:
@@ -1119,6 +1164,8 @@ pub struct UpvarBorrow {
 
 pub type UpvarBorrowMap = FnvHashMap<UpvarId, UpvarBorrow>;
 
+impl Copy for UpvarBorrow {}
+
 impl Region {
     pub fn is_bound(&self) -> bool {
         match *self {
@@ -1136,6 +1183,8 @@ impl Region {
     }
 }
 
+impl Copy for Region {}
+
 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
 /// A "free" region `fr` can be interpreted as "some region
 /// at least as big as the scope `fr.scope`".
@@ -1144,6 +1193,8 @@ pub struct FreeRegion {
     pub bound_region: BoundRegion
 }
 
+impl Copy for FreeRegion {}
+
 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
 pub enum BoundRegion {
     /// An anonymous region parameter for a given fn (&T)
@@ -1163,6 +1214,8 @@ pub enum BoundRegion {
     BrEnv
 }
 
+impl Copy for BoundRegion {}
+
 #[inline]
 pub fn mk_prim_t<'tcx>(primitive: &'tcx TyS<'static>) -> Ty<'tcx> {
     // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
@@ -1302,6 +1355,8 @@ pub enum IntVarValue {
     UintType(ast::UintTy),
 }
 
+impl Copy for IntVarValue {}
+
 #[deriving(Clone, Show)]
 pub enum terr_vstore_kind {
     terr_vec,
@@ -1310,12 +1365,16 @@ pub enum terr_vstore_kind {
     terr_trait
 }
 
+impl Copy for terr_vstore_kind {}
+
 #[deriving(Clone, Show)]
 pub struct expected_found<T> {
     pub expected: T,
     pub found: T
 }
 
+impl<T:Copy> Copy for expected_found<T> {}
+
 // Data structures used in type unification
 #[deriving(Clone, Show)]
 pub enum type_err<'tcx> {
@@ -1350,6 +1409,8 @@ pub enum type_err<'tcx> {
     terr_convergence_mismatch(expected_found<bool>)
 }
 
+impl<'tcx> Copy for type_err<'tcx> {}
+
 /// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
 /// as well as the existential type parameter in an object type.
 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
@@ -1370,6 +1431,8 @@ pub struct ExistentialBounds {
     pub builtin_bounds: BuiltinBounds
 }
 
+impl Copy for ExistentialBounds {}
+
 pub type BuiltinBounds = EnumSet<BuiltinBound>;
 
 #[deriving(Clone, Encodable, PartialEq, Eq, Decodable, Hash, Show)]
@@ -1381,6 +1444,8 @@ pub enum BuiltinBound {
     BoundSync,
 }
 
+impl Copy for BuiltinBound {}
+
 pub fn empty_builtin_bounds() -> BuiltinBounds {
     EnumSet::new()
 }
@@ -1413,21 +1478,29 @@ pub struct TyVid {
     pub index: uint
 }
 
+impl Copy for TyVid {}
+
 #[deriving(Clone, PartialEq, Eq, Hash)]
 pub struct IntVid {
     pub index: uint
 }
 
+impl Copy for IntVid {}
+
 #[deriving(Clone, PartialEq, Eq, Hash)]
 pub struct FloatVid {
     pub index: uint
 }
 
+impl Copy for FloatVid {}
+
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct RegionVid {
     pub index: uint
 }
 
+impl Copy for RegionVid {}
+
 #[deriving(Clone, PartialEq, Eq, Hash)]
 pub enum InferTy {
     TyVar(TyVid),
@@ -1441,12 +1514,16 @@ pub enum InferTy {
     SkolemizedIntTy(uint),
 }
 
+impl Copy for InferTy {}
+
 #[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)]
 pub enum InferRegion {
     ReVar(RegionVid),
     ReSkolemized(uint, BoundRegion)
 }
 
+impl Copy for InferRegion {}
+
 impl cmp::PartialEq for InferRegion {
     fn eq(&self, other: &InferRegion) -> bool {
         match ((*self), *other) {
@@ -1642,6 +1719,7 @@ impl<'tcx> TraitRef<'tcx> {
 /// bound lifetime parameters are replaced with free ones, but in the
 /// future I hope to refine the representation of types so as to make
 /// more distinctions clearer.
+#[deriving(Clone)]
 pub struct ParameterEnvironment<'tcx> {
     /// A substitution that can be applied to move from
     /// the "outer" view of a type or method to the "inner" view.
@@ -1690,14 +1768,14 @@ impl<'tcx> ParameterEnvironment<'tcx> {
                             }
                             TypeTraitItem(_) => {
                                 cx.sess
-                                  .bug("ParameterEnvironment::from_item(): \
+                                  .bug("ParameterEnvironment::for_item(): \
                                         can't create a parameter environment \
                                         for type trait items")
                             }
                         }
                     }
                     ast::TypeImplItem(_) => {
-                        cx.sess.bug("ParameterEnvironment::from_item(): \
+                        cx.sess.bug("ParameterEnvironment::for_item(): \
                                      can't create a parameter environment \
                                      for type impl items")
                     }
@@ -1707,7 +1785,7 @@ impl<'tcx> ParameterEnvironment<'tcx> {
                 match *trait_method {
                     ast::RequiredMethod(ref required) => {
                         cx.sess.span_bug(required.span,
-                                         "ParameterEnvironment::from_item():
+                                         "ParameterEnvironment::for_item():
                                           can't create a parameter \
                                           environment for required trait \
                                           methods")
@@ -1725,7 +1803,7 @@ impl<'tcx> ParameterEnvironment<'tcx> {
                             }
                             TypeTraitItem(_) => {
                                 cx.sess
-                                  .bug("ParameterEnvironment::from_item(): \
+                                  .bug("ParameterEnvironment::for_item(): \
                                         can't create a parameter environment \
                                         for type trait items")
                             }
@@ -1768,6 +1846,10 @@ impl<'tcx> ParameterEnvironment<'tcx> {
                     }
                 }
             }
+            Some(ast_map::NodeExpr(..)) => {
+                // This is a convenience to allow closures to work.
+                ParameterEnvironment::for_item(cx, cx.map.get_parent(id))
+            }
             _ => {
                 cx.sess.bug(format!("ParameterEnvironment::from_item(): \
                                      `{}` is not an item",
@@ -1825,6 +1907,8 @@ pub enum UnboxedClosureKind {
     FnOnceUnboxedClosureKind,
 }
 
+impl Copy for UnboxedClosureKind {}
+
 impl UnboxedClosureKind {
     pub fn trait_did(&self, cx: &ctxt) -> ast::DefId {
         let result = match *self {
@@ -1909,6 +1993,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
         associated_types: RefCell::new(DefIdMap::new()),
         selection_cache: traits::SelectionCache::new(),
         repr_hint_cache: RefCell::new(DefIdMap::new()),
+        type_moves_by_default_cache: RefCell::new(HashMap::new()),
    }
 }
 
@@ -2604,6 +2689,8 @@ pub struct TypeContents {
     pub bits: u64
 }
 
+impl Copy for TypeContents {}
+
 macro_rules! def_type_content_sets(
     (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
         #[allow(non_snake_case)]
@@ -2630,7 +2717,6 @@ def_type_content_sets!(
         OwnsOwned                           = 0b0000_0000__0000_0001__0000,
         OwnsDtor                            = 0b0000_0000__0000_0010__0000,
         OwnsManaged /* see [1] below */     = 0b0000_0000__0000_0100__0000,
-        OwnsAffine                          = 0b0000_0000__0000_1000__0000,
         OwnsAll                             = 0b0000_0000__1111_1111__0000,
 
         // Things that are reachable by the value in any way (fourth nibble):
@@ -2640,24 +2726,12 @@ def_type_content_sets!(
         ReachesFfiUnsafe                    = 0b0010_0000__0000_0000__0000,
         ReachesAll                          = 0b0011_1111__0000_0000__0000,
 
-        // Things that cause values to *move* rather than *copy*. This
-        // is almost the same as the `Copy` trait, but for managed
-        // data -- atm, we consider managed data to copy, not move,
-        // but it does not impl Copy as a pure memcpy is not good
-        // enough. Yuck.
-        Moves                               = 0b0000_0000__0000_1011__0000,
-
         // Things that mean drop glue is necessary
         NeedsDrop                           = 0b0000_0000__0000_0111__0000,
 
         // Things that prevent values from being considered sized
         Nonsized                            = 0b0000_0000__0000_0000__0001,
 
-        // Things that make values considered not POD (would be same
-        // as `Moves`, but for the fact that managed data `@` is
-        // not considered POD)
-        Noncopy                              = 0b0000_0000__0000_1111__0000,
-
         // Bits to set when a managed value is encountered
         //
         // [1] Do not set the bits TC::OwnsManaged or
@@ -2699,10 +2773,6 @@ impl TypeContents {
         self.intersects(TC::InteriorUnsized)
     }
 
-    pub fn moves_by_default(&self, _: &ctxt) -> bool {
-        self.intersects(TC::Moves)
-    }
-
     pub fn needs_drop(&self, _: &ctxt) -> bool {
         self.intersects(TC::NeedsDrop)
     }
@@ -2987,15 +3057,10 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
         mc | tc_ty(cx, mt.ty, cache)
     }
 
-    fn apply_lang_items(cx: &ctxt,
-                        did: ast::DefId,
-                        tc: TypeContents)
-                        -> TypeContents
-    {
+    fn apply_lang_items(cx: &ctxt, did: ast::DefId, tc: TypeContents)
+                        -> TypeContents {
         if Some(did) == cx.lang_items.managed_bound() {
             tc | TC::Managed
-        } else if Some(did) == cx.lang_items.no_copy_bound() {
-            tc | TC::OwnsAffine
         } else if Some(did) == cx.lang_items.unsafe_type() {
             tc | TC::InteriorUnsafe
         } else {
@@ -3008,7 +3073,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
                          mutbl: ast::Mutability)
                          -> TypeContents {
         let b = match mutbl {
-            ast::MutMutable => TC::ReachesMutable | TC::OwnsAffine,
+            ast::MutMutable => TC::ReachesMutable,
             ast::MutImmutable => TC::None,
         };
         b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
@@ -3028,14 +3093,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
             }
         };
 
-        // This also prohibits "@once fn" from being copied, which allows it to
-        // be called. Neither way really makes much sense.
-        let ot = match cty.onceness {
-            ast::Once => TC::OwnsAffine,
-            ast::Many => TC::None,
-        };
-
-        st | ot
+        st
     }
 
     fn object_contents(cx: &ctxt,
@@ -3053,9 +3111,8 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
         let mut tc = TC::All;
         each_inherited_builtin_bound(cx, bounds, traits, |bound| {
             tc = tc - match bound {
-                BoundSync | BoundSend => TC::None,
+                BoundSync | BoundSend | BoundCopy => TC::None,
                 BoundSized => TC::Nonsized,
-                BoundCopy => TC::Noncopy,
             };
         });
         return tc;
@@ -3081,8 +3138,38 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
     }
 }
 
-pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    type_contents(cx, ty).moves_by_default(cx)
+pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>,
+                                   ty: Ty<'tcx>,
+                                   param_env: &ParameterEnvironment<'tcx>)
+                                    -> bool {
+    if !type_has_params(ty) && !type_has_self(ty) {
+        match cx.type_moves_by_default_cache.borrow().get(&ty) {
+            None => {}
+            Some(&result) => {
+                debug!("determined whether {} moves by default (cached): {}",
+                       ty_to_string(cx, ty),
+                       result);
+                return result
+            }
+        }
+    }
+
+    let infcx = infer::new_infer_ctxt(cx);
+    let mut fulfill_cx = traits::FulfillmentContext::new();
+    let obligation = traits::obligation_for_builtin_bound(
+        cx,
+        ObligationCause::misc(DUMMY_SP),
+        ty,
+        ty::BoundCopy).unwrap();
+    fulfill_cx.register_obligation(cx, obligation);
+    let result = !fulfill_cx.select_all_or_error(&infcx,
+                                                 param_env,
+                                                 cx).is_ok();
+    cx.type_moves_by_default_cache.borrow_mut().insert(ty, result);
+    debug!("determined whether {} moves by default: {}",
+           ty_to_string(cx, ty),
+           result);
+    result
 }
 
 pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
@@ -3214,6 +3301,8 @@ pub enum Representability {
     SelfRecursive,
 }
 
+impl Copy for Representability {}
+
 /// Check whether a type is representable. This means it cannot contain unboxed
 /// structural recursion. This check is needed for structs and enums.
 pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
@@ -3996,6 +4085,8 @@ pub enum ExprKind {
     RvalueStmtExpr
 }
 
+impl Copy for ExprKind {}
+
 pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
     if tcx.method_map.borrow().contains_key(&MethodCall::expr(expr.id)) {
         // Overloaded operations are generally calls, and hence they are
@@ -4555,6 +4646,8 @@ pub struct AssociatedTypeInfo {
     pub name: ast::Name,
 }
 
+impl Copy for AssociatedTypeInfo {}
+
 impl PartialOrd for AssociatedTypeInfo {
     fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option<Ordering> {
         Some(self.index.cmp(&other.index))
@@ -4738,6 +4831,8 @@ pub enum DtorKind {
     TraitDtor(DefId, bool)
 }
 
+impl Copy for DtorKind {}
+
 impl DtorKind {
     pub fn is_present(&self) -> bool {
         match *self {
@@ -5125,6 +5220,8 @@ pub struct UnboxedClosureUpvar<'tcx> {
     pub ty: Ty<'tcx>,
 }
 
+impl<'tcx> Copy for UnboxedClosureUpvar<'tcx> {}
+
 // Returns a list of `UnboxedClosureUpvar`s for each upvar.
 pub fn unboxed_closure_upvars<'tcx>(tcx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &Substs<'tcx>)
                                     -> Vec<UnboxedClosureUpvar<'tcx>> {
@@ -5954,6 +6051,8 @@ pub enum ExplicitSelfCategory {
     ByBoxExplicitSelfCategory,
 }
 
+impl Copy for ExplicitSelfCategory {}
+
 /// Pushes all the lifetimes in the given type onto the given list. A
 /// "lifetime in a type" is a lifetime specified by a reference or a lifetime
 /// in a list of type substitutions. This does *not* traverse into nominal
@@ -6023,6 +6122,8 @@ pub struct Freevar {
     pub span: Span
 }
 
+impl Copy for Freevar {}
+
 pub type FreevarMap = NodeMap<Vec<Freevar>>;
 
 pub type CaptureModeMap = NodeMap<ast::CaptureClause>;
@@ -6122,6 +6223,8 @@ impl DebruijnIndex {
     }
 }
 
+impl Copy for DebruijnIndex {}
+
 impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         match *self {
@@ -6229,3 +6332,43 @@ pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>,
     trait_ref.substs.clone().with_method(meth_tps, meth_regions)
 }
 
+pub enum CopyImplementationError {
+    FieldDoesNotImplementCopy(ast::Name),
+    VariantDoesNotImplementCopy(ast::Name),
+    TypeIsStructural,
+}
+
+impl Copy for CopyImplementationError {}
+
+pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>,
+                                     self_type: Ty<'tcx>,
+                                     param_env: &ParameterEnvironment<'tcx>)
+                                     -> Result<(),CopyImplementationError> {
+    match self_type.sty {
+        ty::ty_struct(struct_did, ref substs) => {
+            let fields = ty::struct_fields(tcx, struct_did, substs);
+            for field in fields.iter() {
+                if type_moves_by_default(tcx, field.mt.ty, param_env) {
+                    return Err(FieldDoesNotImplementCopy(field.name))
+                }
+            }
+        }
+        ty::ty_enum(enum_did, ref substs) => {
+            let enum_variants = ty::enum_variants(tcx, enum_did);
+            for variant in enum_variants.iter() {
+                for variant_arg_type in variant.args.iter() {
+                    let substd_arg_type =
+                        variant_arg_type.subst(tcx, substs);
+                    if type_moves_by_default(tcx,
+                                             substd_arg_type,
+                                             param_env) {
+                        return Err(VariantDoesNotImplementCopy(variant.name))
+                    }
+                }
+            }
+        }
+        _ => return Err(TypeIsStructural),
+    }
+
+    Ok(())
+}
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 981b58a3b7b..c7b5e1e8de9 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -55,6 +55,8 @@ pub enum OptLevel {
     Aggressive // -O3
 }
 
+impl Copy for OptLevel {}
+
 #[deriving(Clone, PartialEq)]
 pub enum DebugInfoLevel {
     NoDebugInfo,
@@ -62,6 +64,8 @@ pub enum DebugInfoLevel {
     FullDebugInfo,
 }
 
+impl Copy for DebugInfoLevel {}
+
 #[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
 pub enum OutputType {
     OutputTypeBitcode,
@@ -71,6 +75,8 @@ pub enum OutputType {
     OutputTypeExe,
 }
 
+impl Copy for OutputType {}
+
 #[deriving(Clone)]
 pub struct Options {
     // The crate config requested for the session, which may be combined
@@ -87,7 +93,7 @@ pub struct Options {
     // parsed code. It remains mutable in case its replacements wants to use
     // this.
     pub addl_lib_search_paths: RefCell<Vec<Path>>,
-    pub libs: Vec<(String, cstore::NativeLibaryKind)>,
+    pub libs: Vec<(String, cstore::NativeLibraryKind)>,
     pub maybe_sysroot: Option<Path>,
     pub target_triple: String,
     // User-specified cfg meta items. The compiler itself will add additional
@@ -221,6 +227,8 @@ pub enum EntryFnType {
     EntryNone,
 }
 
+impl Copy for EntryFnType {}
+
 #[deriving(PartialEq, PartialOrd, Clone, Ord, Eq, Hash)]
 pub enum CrateType {
     CrateTypeExecutable,
@@ -229,6 +237,8 @@ pub enum CrateType {
     CrateTypeStaticlib,
 }
 
+impl Copy for CrateType {}
+
 macro_rules! debugging_opts(
     ([ $opt:ident ] $cnt:expr ) => (
         pub const $opt: u64 = 1 << $cnt;
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index ea252d9fd20..30318cc129c 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -25,6 +25,8 @@ use syntax::visit::Visitor;
 #[deriving(Clone,Show)]
 pub struct ErrorReported;
 
+impl Copy for ErrorReported {}
+
 pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
     thread_local!(static DEPTH: Cell<uint> = Cell::new(0));
     if !do_it { return f(u); }
diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs
index 4dd6306c3c0..d1816c655fa 100644
--- a/src/librustc/util/nodemap.rs
+++ b/src/librustc/util/nodemap.rs
@@ -71,6 +71,9 @@ pub mod DefIdSet {
 #[deriving(Clone, Default)]
 pub struct FnvHasher;
 
+impl Copy for FnvHasher {}
+
+#[allow(missing_copy_implementations)]
 pub struct FnvState(u64);
 
 impl Hasher<FnvState> for FnvHasher {