diff options
Diffstat (limited to 'src/librustc')
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, + ¶meter_environment) { + return + } + if ty::can_type_implement_copy(cx.tcx, + ty, + ¶meter_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: ¶m_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 { |
