From 7701154f8cfea4bd0f9b0954d54c2398fbdd795c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Jun 2013 11:33:14 -0700 Subject: [PATCH 01/13] librustc: Rename Owned to Send in the compiler --- src/libextra/rc.rs | 2 ++ src/librustc/metadata/tydecode.rs | 2 +- src/librustc/metadata/tyencode.rs | 2 +- src/librustc/middle/kind.rs | 28 ++++++++-------- src/librustc/middle/lang_items.rs | 13 ++++---- src/librustc/middle/ty.rs | 48 ++++++++++++++------------- src/librustc/middle/typeck/astconv.rs | 8 ++--- src/librustc/util/ppaux.rs | 4 +-- src/libstd/kinds.rs | 9 ++++- 9 files changed, 63 insertions(+), 53 deletions(-) diff --git a/src/libextra/rc.rs b/src/libextra/rc.rs index 96ad629ea8374..03ad865e845b5 100644 --- a/src/libextra/rc.rs +++ b/src/libextra/rc.rs @@ -36,6 +36,7 @@ struct RcBox { /// Immutable reference counted pointer type #[non_owned] +#[non_sendable] pub struct Rc { priv ptr: *mut RcBox, } @@ -165,6 +166,7 @@ struct RcMutBox { /// Mutable reference counted pointer type #[non_owned] +#[non_sendable] #[mutable] pub struct RcMut { priv ptr: *mut RcMutBox, diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index cf2a92b291f28..6295bbab1bb53 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -555,7 +555,7 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds { loop { match next(st) { 'S' => { - param_bounds.builtin_bounds.add(ty::BoundOwned); + param_bounds.builtin_bounds.add(ty::BoundSend); } 'C' => { param_bounds.builtin_bounds.add(ty::BoundCopy); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index d9377afa9a527..4c784c13d2c88 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -399,7 +399,7 @@ fn enc_fn_sig(w: @io::Writer, cx: @ctxt, fsig: &ty::FnSig) { fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: &ty::ParamBounds) { for bs.builtin_bounds.each |bound| { match bound { - ty::BoundOwned => w.write_char('S'), + ty::BoundSend => w.write_char('S'), ty::BoundCopy => w.write_char('C'), ty::BoundConst => w.write_char('K'), ty::BoundStatic => w.write_char('O'), diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index a4cac540a7e78..3eb625e63bc86 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -35,7 +35,7 @@ use syntax::{visit, ast_util}; // copy: Things that can be copied. // const: Things thare are deeply immutable. They are guaranteed never to // change, and can be safely shared without copying between tasks. -// owned: Things that do not contain borrowed pointers. +// 'static: Things that do not contain borrowed pointers. // // Send includes scalar types as well as classes and unique types containing // only sendable types. @@ -94,10 +94,10 @@ fn check_struct_safe_for_destructor(cx: Context, self_ty: None, tps: ~[] }); - if !ty::type_is_owned(cx.tcx, struct_ty) { + if !ty::type_is_sendable(cx.tcx, struct_ty) { cx.tcx.sess.span_err(span, - "cannot implement a destructor on a struct \ - that is not Owned"); + "cannot implement a destructor on a \ + structure that does not satisfy Send"); cx.tcx.sess.span_note(span, "use \"#[unsafe_destructor]\" on the \ implementation to force the compiler to \ @@ -105,7 +105,7 @@ fn check_struct_safe_for_destructor(cx: Context, } } else { cx.tcx.sess.span_err(span, - "cannot implement a destructor on a struct \ + "cannot implement a destructor on a structure \ with type parameters"); cx.tcx.sess.span_note(span, "use \"#[unsafe_destructor]\" on the \ @@ -165,18 +165,18 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt)) { // closure. fn with_appropriate_checker(cx: Context, id: node_id, b: &fn(check_fn)) { fn check_for_uniq(cx: Context, fv: @freevar_entry) { - // all captured data must be owned, regardless of whether it is + // all captured data must be sendable, regardless of whether it is // moved in or copied in. let id = ast_util::def_id_of_def(fv.def).node; let var_t = ty::node_id_to_type(cx.tcx, id); - if !check_owned(cx, var_t, fv.span) { return; } + if !check_send(cx, var_t, fv.span) { return; } // check that only immutable variables are implicitly copied in check_imm_free_var(cx, fv.def, fv.span); } fn check_for_box(cx: Context, fv: @freevar_entry) { - // all captured data must be owned + // all captured data must be durable let id = ast_util::def_id_of_def(fv.def).node; let var_t = ty::node_id_to_type(cx.tcx, id); if !check_durable(cx.tcx, var_t, fv.span) { return; } @@ -393,10 +393,10 @@ fn check_copy(cx: Context, ty: ty::t, sp: span, reason: &str) { } } -pub fn check_owned(cx: Context, ty: ty::t, sp: span) -> bool { - if !ty::type_is_owned(cx.tcx, ty) { +pub fn check_send(cx: Context, ty: ty::t, sp: span) -> bool { + if !ty::type_is_sendable(cx.tcx, ty) { cx.tcx.sess.span_err( - sp, fmt!("value has non-owned type `%s`", + sp, fmt!("value has non-sendable type `%s`", ty_to_str(cx.tcx, ty))); false } else { @@ -444,7 +444,7 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool { /// `deque`, then whatever borrowed ptrs may appear in `T` also /// appear in `deque`. /// -/// (3) The type parameter is owned (and therefore does not contain +/// (3) The type parameter is sendable (and therefore does not contain /// borrowed ptrs). /// /// FIXME(#5723)---This code should probably move into regionck. @@ -483,7 +483,7 @@ pub fn check_cast_for_escaping_regions( } // Assuming the trait instance can escape, then ensure that each parameter - // either appears in the trait type or is owned. + // either appears in the trait type or is sendable. let target_params = ty::param_tys_in_type(target_ty); let source_ty = ty::expr_ty(cx.tcx, source); ty::walk_regions_and_ty( @@ -536,7 +536,7 @@ pub fn check_kind_bounds_of_cast(cx: Context, source: @expr, target: @expr) { match ty::get(target_ty).sty { ty::ty_trait(_, _, ty::UniqTraitStore, _) => { let source_ty = ty::expr_ty(cx.tcx, source); - if !ty::type_is_owned(cx.tcx, source_ty) { + if !ty::type_is_sendable(cx.tcx, source_ty) { cx.tcx.sess.span_err( target.span, "uniquely-owned trait objects must be sendable"); diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index eaf05a4a85ff9..3cfc50fe5a080 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -13,7 +13,7 @@ // Language items are items that represent concepts intrinsic to the language // itself. Examples are: // -// * Traits that specify "kinds"; e.g. "const", "copy", "owned". +// * Traits that specify "kinds"; e.g. "const", "copy", "send". // // * Traits that represent operators; e.g. "add", "sub", "index". // @@ -35,7 +35,7 @@ use core::hashmap::HashMap; pub enum LangItem { ConstTraitLangItem, // 0 CopyTraitLangItem, // 1 - OwnedTraitLangItem, // 2 + SendTraitLangItem, // 2 SizedTraitLangItem, // 3 DropTraitLangItem, // 4 @@ -97,7 +97,7 @@ impl LanguageItems { match index { 0 => "const", 1 => "copy", - 2 => "owned", + 2 => "send", 3 => "sized", 4 => "drop", @@ -150,8 +150,8 @@ impl LanguageItems { pub fn copy_trait(&const self) -> def_id { self.items[CopyTraitLangItem as uint].get() } - pub fn owned_trait(&const self) -> def_id { - self.items[OwnedTraitLangItem as uint].get() + pub fn send_trait(&const self) -> def_id { + self.items[SendTraitLangItem as uint].get() } pub fn sized_trait(&const self) -> def_id { self.items[SizedTraitLangItem as uint].get() @@ -271,7 +271,7 @@ fn LanguageItemCollector(crate: @crate, item_refs.insert(@"const", ConstTraitLangItem as uint); item_refs.insert(@"copy", CopyTraitLangItem as uint); - item_refs.insert(@"owned", OwnedTraitLangItem as uint); + item_refs.insert(@"send", SendTraitLangItem as uint); item_refs.insert(@"sized", SizedTraitLangItem as uint); item_refs.insert(@"drop", DropTraitLangItem as uint); @@ -299,7 +299,6 @@ fn LanguageItemCollector(crate: @crate, item_refs.insert(@"log_type", LogTypeFnLangItem as uint); item_refs.insert(@"fail_", FailFnLangItem as uint); item_refs.insert(@"fail_bounds_check", - FailBoundsCheckFnLangItem as uint); item_refs.insert(@"exchange_malloc", ExchangeMallocFnLangItem as uint); item_refs.insert(@"exchange_free", ExchangeFreeFnLangItem as uint); item_refs.insert(@"malloc", MallocFnLangItem as uint); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fe533f6ad80a5..7b44dd2684744 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -686,7 +686,7 @@ pub type BuiltinBounds = EnumSet; pub enum BuiltinBound { BoundCopy, BoundStatic, - BoundOwned, + BoundSend, BoundConst, BoundSized, } @@ -699,7 +699,7 @@ pub fn AllBuiltinBounds() -> BuiltinBounds { let mut set = EnumSet::empty(); set.add(BoundCopy); set.add(BoundStatic); - set.add(BoundOwned); + set.add(BoundSend); set.add(BoundConst); set.add(BoundSized); set @@ -1834,7 +1834,7 @@ impl TypeContents { BoundCopy => self.is_copy(cx), BoundStatic => self.is_static(cx), BoundConst => self.is_const(cx), - BoundOwned => self.is_owned(cx), + BoundSend => self.is_sendable(cx), BoundSized => self.is_sized(cx), } } @@ -1860,12 +1860,12 @@ impl TypeContents { TC_BORROWED_POINTER } - pub fn is_owned(&self, cx: ctxt) -> bool { - !self.intersects(TypeContents::nonowned(cx)) + pub fn is_sendable(&self, cx: ctxt) -> bool { + !self.intersects(TypeContents::nonsendable(cx)) } - pub fn nonowned(_cx: ctxt) -> TypeContents { - TC_MANAGED + TC_BORROWED_POINTER + TC_NON_OWNED + pub fn nonsendable(_cx: ctxt) -> TypeContents { + TC_MANAGED + TC_BORROWED_POINTER + TC_NON_SENDABLE } pub fn contains_managed(&self) -> bool { @@ -1897,12 +1897,12 @@ impl TypeContents { } pub fn needs_drop(&self, cx: ctxt) -> bool { - let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx); + let tc = TC_MANAGED + TC_DTOR + TypeContents::sendable(cx); self.intersects(tc) } - pub fn owned(_cx: ctxt) -> TypeContents { - //! Any kind of owned contents. + pub fn sendable(_cx: ctxt) -> TypeContents { + //! Any kind of sendable contents. TC_OWNED_CLOSURE + TC_OWNED_POINTER + TC_OWNED_VEC } } @@ -1958,8 +1958,8 @@ static TC_ONCE_CLOSURE: TypeContents = TypeContents{bits: 0b0001_0000_0000}; /// An enum with no variants. static TC_EMPTY_ENUM: TypeContents = TypeContents{bits: 0b0010_0000_0000}; -/// Contains a type marked with `#[non_owned]` -static TC_NON_OWNED: TypeContents = TypeContents{bits: 0b0100_0000_0000}; +/// Contains a type marked with `#[non_sendable]` +static TC_NON_SENDABLE: TypeContents = TypeContents{bits: 0b0100_0000_0000}; /// Is a bare vector, str, function, trait, etc (only relevant at top level). static TC_DYNAMIC_SIZE: TypeContents = TypeContents{bits: 0b1000_0000_0000}; @@ -1975,8 +1975,8 @@ pub fn type_is_static(cx: ctxt, t: ty::t) -> bool { type_contents(cx, t).is_static(cx) } -pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool { - type_contents(cx, t).is_owned(cx) +pub fn type_is_sendable(cx: ctxt, t: ty::t) -> bool { + type_contents(cx, t).is_sendable(cx) } pub fn type_is_const(cx: ctxt, t: ty::t) -> bool { @@ -2034,7 +2034,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { let _i = indenter(); let result = match get(ty).sty { - // Scalar and unique types are sendable, constant, and owned + // Scalar and unique types are sendable, constant, and durable ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_bare_fn(_) | ty_ptr(_) => { TC_NONE @@ -2049,7 +2049,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { } ty_box(mt) => { - TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache))) + TC_MANAGED + + statically_sized(nonsendable(tc_mt(cx, mt, cache))) } ty_trait(_, _, UniqTraitStore, _) => { @@ -2069,7 +2070,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { ty_rptr(r, mt) => { borrowed_contents(r, mt.mutbl) + - statically_sized(nonowned(tc_mt(cx, mt, cache))) + statically_sized(nonsendable(tc_mt(cx, mt, cache))) } ty_uniq(mt) => { @@ -2081,12 +2082,13 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { } ty_evec(mt, vstore_box) => { - TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache))) + TC_MANAGED + + statically_sized(nonsendable(tc_mt(cx, mt, cache))) } ty_evec(mt, vstore_slice(r)) => { borrowed_contents(r, mt.mutbl) + - statically_sized(nonowned(tc_mt(cx, mt, cache))) + statically_sized(nonsendable(tc_mt(cx, mt, cache))) } ty_evec(mt, vstore_fixed(_)) => { @@ -2204,8 +2206,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { if has_attr(cx, did, "mutable") { tc += TC_MUTABLE; } - if has_attr(cx, did, "non_owned") { - tc += TC_NON_OWNED; + if has_attr(cx, did, "non_sendable") { + tc += TC_NON_SENDABLE; } tc } @@ -2226,7 +2228,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { mc + rc } - fn nonowned(pointee: TypeContents) -> TypeContents { + fn nonsendable(pointee: TypeContents) -> TypeContents { /*! * * Given a non-owning pointer to some type `T` with @@ -2273,7 +2275,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { tc = tc - match bound { BoundCopy => TypeContents::nonimplicitly_copyable(cx), BoundStatic => TypeContents::nonstatic(cx), - BoundOwned => TypeContents::nonowned(cx), + BoundSend => TypeContents::nonsendable(cx), BoundConst => TypeContents::nonconst(cx), // The dynamic-size bit can be removed at pointer-level, etc. BoundSized => TypeContents::dynamically_sized(cx), diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 4b5f416cdd172..b4a6687b17e59 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -733,7 +733,7 @@ fn conv_builtin_bounds(tcx: ty::ctxt, //! Converts a list of bounds from the AST into a `BuiltinBounds` //! struct. Reports an error if any of the bounds that appear //! in the AST refer to general traits and not the built-in traits - //! like `Copy` or `Owned`. Used to translate the bounds that + //! like `Copy` or `Send`. Used to translate the bounds that //! appear in closure and trait types, where only builtin bounds are //! legal. @@ -768,13 +768,13 @@ pub fn try_add_builtin_trait(tcx: ty::ctxt, trait_def_id: ast::def_id, builtin_bounds: &mut ty::BuiltinBounds) -> bool { //! Checks whether `trait_ref` refers to one of the builtin - //! traits, like `Copy` or `Owned`, and adds the corresponding + //! traits, like `Copy` or `Send`, and adds the corresponding //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref` //! is a builtin trait. let li = &tcx.lang_items; - if trait_def_id == li.owned_trait() { - builtin_bounds.add(ty::BoundOwned); + if trait_def_id == li.send_trait() { + builtin_bounds.add(ty::BoundSend); true } else if trait_def_id == li.copy_trait() { builtin_bounds.add(ty::BoundCopy); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 4979f5acf63c6..3b96b07208dc1 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -562,7 +562,7 @@ impl Repr for ty::ParamBounds { res.push(match b { ty::BoundCopy => ~"Copy", ty::BoundStatic => ~"'static", - ty::BoundOwned => ~"Owned", + ty::BoundSend => ~"Send", ty::BoundConst => ~"Const", ty::BoundSized => ~"Sized", }); @@ -768,7 +768,7 @@ impl UserString for ty::BuiltinBound { match *self { ty::BoundCopy => ~"Copy", ty::BoundStatic => ~"'static", - ty::BoundOwned => ~"Owned", + ty::BoundSend => ~"Send", ty::BoundConst => ~"Const", ty::BoundSized => ~"Sized", } diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index 05c963a32cc73..123468cad88e1 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -44,9 +44,16 @@ pub trait Copy { // Empty. } +#[cfg(stage0)] #[lang="owned"] pub trait Owned { - // Empty. + // empty. +} + +#[cfg(not(stage0))] +#[lang="send"] +pub trait Owned { + // empty. } #[lang="const"] From 21adf433505aff473f9361b1ed0252d0a34ffde5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Jun 2013 14:52:27 -0700 Subject: [PATCH 02/13] librustc: Change Const to Freeze in the compiler --- src/librustc/metadata/tydecode.rs | 2 +- src/librustc/metadata/tyencode.rs | 2 +- src/librustc/middle/kind.rs | 8 ++++---- src/librustc/middle/lang_items.rs | 14 +++++++------- src/librustc/middle/ty.rs | 20 ++++++++++---------- src/librustc/middle/typeck/astconv.rs | 4 ++-- src/librustc/util/ppaux.rs | 4 ++-- src/libstd/kinds.rs | 12 +++++++++--- src/libstd/prelude.rs | 3 ++- 9 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 6295bbab1bb53..6cab5ca3ddcdf 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -561,7 +561,7 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds { param_bounds.builtin_bounds.add(ty::BoundCopy); } 'K' => { - param_bounds.builtin_bounds.add(ty::BoundConst); + param_bounds.builtin_bounds.add(ty::BoundFreeze); } 'O' => { param_bounds.builtin_bounds.add(ty::BoundStatic); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 4c784c13d2c88..d233021121411 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -401,7 +401,7 @@ fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: &ty::ParamBounds) { match bound { ty::BoundSend => w.write_char('S'), ty::BoundCopy => w.write_char('C'), - ty::BoundConst => w.write_char('K'), + ty::BoundFreeze => w.write_char('K'), ty::BoundStatic => w.write_char('O'), ty::BoundSized => w.write_char('Z'), } diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 3eb625e63bc86..986df004a75b5 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -33,7 +33,7 @@ use syntax::{visit, ast_util}; // // send: Things that can be sent on channels or included in spawned closures. // copy: Things that can be copied. -// const: Things thare are deeply immutable. They are guaranteed never to +// freeze: Things thare are deeply immutable. They are guaranteed never to // change, and can be safely shared without copying between tasks. // 'static: Things that do not contain borrowed pointers. // @@ -42,12 +42,12 @@ use syntax::{visit, ast_util}; // // Copy includes boxes, closure and unique types containing copyable types. // -// Const include scalar types, things without non-const fields, and pointers -// to const things. +// Freeze include scalar types, things without non-const fields, and pointers +// to freezable things. // // This pass ensures that type parameters are only instantiated with types // whose kinds are equal or less general than the way the type parameter was -// annotated (with the `send`, `copy` or `const` keyword). +// annotated (with the `Send`, `Copy` or `Freeze` bound). // // It also verifies that noncopyable kinds are not copied. Sendability is not // applied, since none of our language primitives send. Instead, the sending diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3cfc50fe5a080..7f1b983a623bd 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -13,9 +13,9 @@ // Language items are items that represent concepts intrinsic to the language // itself. Examples are: // -// * Traits that specify "kinds"; e.g. "const", "copy", "send". +// * Traits that specify "kinds"; e.g. "Freeze", "Copy", "Send". // -// * Traits that represent operators; e.g. "add", "sub", "index". +// * Traits that represent operators; e.g. "Add", "Sub", "Index". // // * Functions called by the compiler itself. @@ -33,7 +33,7 @@ use syntax::visit::visit_crate; use core::hashmap::HashMap; pub enum LangItem { - ConstTraitLangItem, // 0 + FreezeTraitLangItem, // 0 CopyTraitLangItem, // 1 SendTraitLangItem, // 2 SizedTraitLangItem, // 3 @@ -95,7 +95,7 @@ impl LanguageItems { pub fn item_name(index: uint) -> &'static str { match index { - 0 => "const", + 0 => "freeze", 1 => "copy", 2 => "send", 3 => "sized", @@ -144,8 +144,8 @@ impl LanguageItems { // FIXME #4621: Method macros sure would be nice here. - pub fn const_trait(&const self) -> def_id { - self.items[ConstTraitLangItem as uint].get() + pub fn freeze_trait(&const self) -> def_id { + self.items[FreezeTraitLangItem as uint].get() } pub fn copy_trait(&const self) -> def_id { self.items[CopyTraitLangItem as uint].get() @@ -269,7 +269,7 @@ fn LanguageItemCollector(crate: @crate, -> LanguageItemCollector { let mut item_refs = HashMap::new(); - item_refs.insert(@"const", ConstTraitLangItem as uint); + item_refs.insert(@"freeze", FreezeTraitLangItem as uint); item_refs.insert(@"copy", CopyTraitLangItem as uint); item_refs.insert(@"send", SendTraitLangItem as uint); item_refs.insert(@"sized", SizedTraitLangItem as uint); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7b44dd2684744..afb988a07d275 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -687,7 +687,7 @@ pub enum BuiltinBound { BoundCopy, BoundStatic, BoundSend, - BoundConst, + BoundFreeze, BoundSized, } @@ -700,7 +700,7 @@ pub fn AllBuiltinBounds() -> BuiltinBounds { set.add(BoundCopy); set.add(BoundStatic); set.add(BoundSend); - set.add(BoundConst); + set.add(BoundFreeze); set.add(BoundSized); set } @@ -1833,7 +1833,7 @@ impl TypeContents { match bb { BoundCopy => self.is_copy(cx), BoundStatic => self.is_static(cx), - BoundConst => self.is_const(cx), + BoundFreeze => self.is_freezable(cx), BoundSend => self.is_sendable(cx), BoundSized => self.is_sized(cx), } @@ -1872,11 +1872,11 @@ impl TypeContents { self.intersects(TC_MANAGED) } - pub fn is_const(&self, cx: ctxt) -> bool { - !self.intersects(TypeContents::nonconst(cx)) + pub fn is_freezable(&self, cx: ctxt) -> bool { + !self.intersects(TypeContents::nonfreezable(cx)) } - pub fn nonconst(_cx: ctxt) -> TypeContents { + pub fn nonfreezable(_cx: ctxt) -> TypeContents { TC_MUTABLE } @@ -1979,8 +1979,8 @@ pub fn type_is_sendable(cx: ctxt, t: ty::t) -> bool { type_contents(cx, t).is_sendable(cx) } -pub fn type_is_const(cx: ctxt, t: ty::t) -> bool { - type_contents(cx, t).is_const(cx) +pub fn type_is_freezable(cx: ctxt, t: ty::t) -> bool { + type_contents(cx, t).is_freezable(cx) } pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { @@ -2034,7 +2034,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { let _i = indenter(); let result = match get(ty).sty { - // Scalar and unique types are sendable, constant, and durable + // Scalar and unique types are sendable, freezable, and durable ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_bare_fn(_) | ty_ptr(_) => { TC_NONE @@ -2276,7 +2276,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { BoundCopy => TypeContents::nonimplicitly_copyable(cx), BoundStatic => TypeContents::nonstatic(cx), BoundSend => TypeContents::nonsendable(cx), - BoundConst => TypeContents::nonconst(cx), + BoundFreeze => TypeContents::nonfreezable(cx), // The dynamic-size bit can be removed at pointer-level, etc. BoundSized => TypeContents::dynamically_sized(cx), }; diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index b4a6687b17e59..bea33ca07d3eb 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -779,8 +779,8 @@ pub fn try_add_builtin_trait(tcx: ty::ctxt, } else if trait_def_id == li.copy_trait() { builtin_bounds.add(ty::BoundCopy); true - } else if trait_def_id == li.const_trait() { - builtin_bounds.add(ty::BoundConst); + } else if trait_def_id == li.freeze_trait() { + builtin_bounds.add(ty::BoundFreeze); true } else if trait_def_id == li.sized_trait() { builtin_bounds.add(ty::BoundSized); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3b96b07208dc1..f7c75bd3c4017 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -563,7 +563,7 @@ impl Repr for ty::ParamBounds { ty::BoundCopy => ~"Copy", ty::BoundStatic => ~"'static", ty::BoundSend => ~"Send", - ty::BoundConst => ~"Const", + ty::BoundFreeze => ~"Freeze", ty::BoundSized => ~"Sized", }); } @@ -769,7 +769,7 @@ impl UserString for ty::BuiltinBound { ty::BoundCopy => ~"Copy", ty::BoundStatic => ~"'static", ty::BoundSend => ~"Send", - ty::BoundConst => ~"Const", + ty::BoundFreeze => ~"Freeze", ty::BoundSized => ~"Sized", } } diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index 123468cad88e1..b7ec90574e29d 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -27,8 +27,7 @@ The 4 kinds are * Owned - owned types and types containing owned types. These types may be transferred across task boundaries. -* Const - types that are deeply immutable. Const types are used for - freezable data structures. +* Freeze - types that are deeply immutable. `Copy` types include both implicitly copyable types that the compiler will copy automatically and non-implicitly copyable types that require @@ -56,9 +55,16 @@ pub trait Owned { // empty. } +#[cfg(stage0)] #[lang="const"] pub trait Const { - // Empty. + // empty. +} + +#[cfg(not(stage0))] +#[lang="freeze"] +pub trait Const { + // empty. } #[lang="sized"] diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 4400cb5de9833..efa40430e3cad 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -29,7 +29,8 @@ Rust's prelude has three main parts: // Reexported core operators pub use either::{Either, Left, Right}; -pub use kinds::{Const, Copy, Owned, Sized}; +pub use kinds::{Copy, Sized}; +pub use kinds::{Const, Owned}; pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Drop}; From cee0dfa5b62e5d6a3187aa8eb23603c9958e2687 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Jun 2013 15:53:17 -0700 Subject: [PATCH 03/13] librustc: Rename Const to Freeze --- src/libextra/arc.rs | 20 ++--- src/libextra/rc.rs | 8 +- src/librustc/metadata/decoder.rs | 10 +-- src/librustc/middle/borrowck/doc.rs | 4 +- .../borrowck/gather_loans/restrictions.rs | 2 +- src/librustc/middle/typeck/collect.rs | 2 +- src/librustdoc/markdown_pass.rs | 4 +- src/libstd/clone.rs | 10 +-- src/libstd/kinds.rs | 4 +- src/libstd/prelude.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/parse/parser.rs | 14 ++-- src/libsyntax/parse/token.rs | 74 +++++++++---------- src/libsyntax/util/interner.rs | 2 +- src/test/auxiliary/issue-2526.rs | 6 +- src/test/compile-fail/issue-2611-4.rs | 2 +- .../compile-fail/issue-3177-mutable-struct.rs | 2 +- src/test/compile-fail/mutable-enum.rs | 4 +- src/test/compile-fail/mutable-struct.rs | 4 +- src/test/run-pass/const-bound.rs | 2 +- src/test/run-pass/issue-2611-3.rs | 2 +- 21 files changed, 90 insertions(+), 90 deletions(-) diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs index 1b6b656e398a4..4c5f90e0dfbed 100644 --- a/src/libextra/arc.rs +++ b/src/libextra/arc.rs @@ -112,7 +112,7 @@ impl<'self> Condvar<'self> { pub struct ARC { x: UnsafeAtomicRcBox } /// Create an atomically reference counted wrapper. -pub fn ARC(data: T) -> ARC { +pub fn ARC(data: T) -> ARC { ARC { x: UnsafeAtomicRcBox::new(data) } } @@ -120,7 +120,7 @@ pub fn ARC(data: T) -> ARC { * Access the underlying data in an atomically reference counted * wrapper. */ -impl ARC { +impl ARC { pub fn get<'a>(&'a self) -> &'a T { unsafe { &*self.x.get_immut() } } @@ -133,7 +133,7 @@ impl ARC { * object. However, one of the `arc` objects can be sent to another task, * allowing them to share the underlying data. */ -impl Clone for ARC { +impl Clone for ARC { fn clone(&self) -> ARC { ARC { x: self.x.clone() } } @@ -285,14 +285,14 @@ struct RWARC { } /// Create a reader/writer ARC with the supplied data. -pub fn RWARC(user_data: T) -> RWARC { +pub fn RWARC(user_data: T) -> RWARC { rw_arc_with_condvars(user_data, 1) } /** * Create a reader/writer ARC with the supplied data and a specified number * of condvars (as sync::rwlock_with_condvars). */ -pub fn rw_arc_with_condvars( +pub fn rw_arc_with_condvars( user_data: T, num_condvars: uint) -> RWARC { @@ -302,7 +302,7 @@ pub fn rw_arc_with_condvars( RWARC { x: UnsafeAtomicRcBox::new(data), cant_nest: () } } -impl RWARC { +impl RWARC { /// Duplicate a rwlock-protected ARC, as arc::clone. pub fn clone(&self) -> RWARC { RWARC { @@ -313,7 +313,7 @@ impl RWARC { } -impl RWARC { +impl RWARC { /** * Access the underlying data mutably. Locks the rwlock in write mode; * other readers and writers will block. @@ -439,7 +439,7 @@ impl RWARC { // lock it. This wraps the unsafety, with the justification that the 'lock' // field is never overwritten; only 'failed' and 'data'. #[doc(hidden)] -fn borrow_rwlock(state: *const RWARCInner) -> *RWlock { +fn borrow_rwlock(state: *const RWARCInner) -> *RWlock { unsafe { cast::transmute(&const (*state).lock) } } @@ -456,7 +456,7 @@ pub struct RWReadMode<'self, T> { token: sync::RWlockReadMode<'self>, } -impl<'self, T:Const + Owned> RWWriteMode<'self, T> { +impl<'self, T:Freeze + Owned> RWWriteMode<'self, T> { /// Access the pre-downgrade RWARC in write mode. pub fn write(&mut self, blk: &fn(x: &mut T) -> U) -> U { match *self { @@ -497,7 +497,7 @@ impl<'self, T:Const + Owned> RWWriteMode<'self, T> { } } -impl<'self, T:Const + Owned> RWReadMode<'self, T> { +impl<'self, T:Freeze + Owned> RWReadMode<'self, T> { /// Access the post-downgrade rwlock in read mode. pub fn read(&self, blk: &fn(x: &T) -> U) -> U { match *self { diff --git a/src/libextra/rc.rs b/src/libextra/rc.rs index 03ad865e845b5..e72939b0a2053 100644 --- a/src/libextra/rc.rs +++ b/src/libextra/rc.rs @@ -13,10 +13,10 @@ /** Task-local reference counted smart pointers Task-local reference counted smart pointers are an alternative to managed boxes with deterministic -destruction. They are restricted to containing types that are either `Owned` or `Const` (or both) to +destruction. They are restricted to containing types that are either `Owned` or `Freeze` (or both) to prevent cycles. -Neither `Rc` or `RcMut` is ever `Owned` and `RcMut` is never `Const`. If `T` is `Const`, a +Neither `Rc` or `RcMut` is ever `Owned` and `RcMut` is never `Freeze`. If `T` is `Freeze`, a cycle cannot be created with `Rc` because there is no way to modify it after creation. */ @@ -56,7 +56,7 @@ pub fn rc_from_owned(value: T) -> Rc { } // FIXME: #6516: should be a static method -pub fn rc_from_const(value: T) -> Rc { +pub fn rc_from_const(value: T) -> Rc { unsafe { Rc::new(value) } } @@ -187,7 +187,7 @@ pub fn rc_mut_from_owned(value: T) -> RcMut { } // FIXME: #6516: should be a static method -pub fn rc_mut_from_const(value: T) -> RcMut { +pub fn rc_mut_from_const(value: T) -> RcMut { unsafe { RcMut::new(value) } } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index fdef25b5e711a..504d0c9120ec5 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -97,7 +97,7 @@ fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc { #[deriving(Eq)] enum Family { - Const, // c + Freeze, // c Fn, // f UnsafeFn, // u PureFn, // p @@ -122,7 +122,7 @@ enum Family { fn item_family(item: ebml::Doc) -> Family { let fam = reader::get_doc(item, tag_items_data_item_family); match reader::doc_as_u8(fam) as char { - 'c' => Const, + 'c' => Freeze, 'f' => Fn, 'u' => UnsafeFn, 'p' => PureFn, @@ -321,7 +321,7 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) -> def_like { let fam = item_family(item); match fam { - Const => dl_def(ast::def_const(did)), + Freeze => dl_def(ast::def_const(did)), Struct => dl_def(ast::def_struct(did)), UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), Fn => dl_def(ast::def_fn(did, ast::impure_fn)), @@ -927,7 +927,7 @@ pub fn get_item_visibility(cdata: cmd, id: ast::node_id) fn family_has_type_params(fam: Family) -> bool { match fam { - Const | ForeignType | Mod | ForeignMod | PublicField | PrivateField + Freeze | ForeignType | Mod | ForeignMod | PublicField | PrivateField | ForeignFn => false, _ => true } @@ -958,7 +958,7 @@ fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str { fn item_family_to_str(fam: Family) -> ~str { match fam { - Const => ~"const", + Freeze => ~"const", Fn => ~"fn", UnsafeFn => ~"unsafe fn", PureFn => ~"pure fn", diff --git a/src/librustc/middle/borrowck/doc.rs b/src/librustc/middle/borrowck/doc.rs index cb3983117e97c..7a91f204b1312 100644 --- a/src/librustc/middle/borrowck/doc.rs +++ b/src/librustc/middle/borrowck/doc.rs @@ -539,14 +539,14 @@ mutable borrowed pointers. ### Restrictions for loans of const aliasable pointees -Const pointers are read-only. There may be `&mut` or `&` aliases, and +Freeze pointers are read-only. There may be `&mut` or `&` aliases, and we can not prevent *anything* but moves in that case. So the `RESTRICTIONS` function is only defined if `ACTIONS` is the empty set. Because moves from a `&const` or `@const` lvalue are never legal, it is not necessary to add any restrictions at all to the final result. - RESTRICTIONS(*LV, []) = [] // R-Deref-Const-Borrowed + RESTRICTIONS(*LV, []) = [] // R-Deref-Freeze-Borrowed TYPE(LV) = &const Ty or @const Ty ### Restrictions for loans of mutable borrowed pointees diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 6bd32f04ce5b9..f54cfb3d1d4ed 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -125,7 +125,7 @@ impl RestrictionsContext { mc::cat_deref(_, _, mc::region_ptr(m_const, _)) | mc::cat_deref(_, _, mc::gc_ptr(m_const)) => { - // R-Deref-Const-Borrowed + // R-Deref-Freeze-Borrowed self.check_no_mutability_control(cmt, restrictions); Safe } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 6ced82df1d735..1e2333dab5611 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1205,7 +1205,7 @@ pub fn ty_generics(ccx: &CrateCtxt, * enum consisting of a newtyped Ty or a region) to ty's * notion of ty param bounds, which can either be user-defined * traits, or one of the four built-in traits (formerly known - * as kinds): Const, Copy, and Send. + * as kinds): Freeze, Copy, and Send. */ let mut param_bounds = ty::ParamBounds { diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 6f480d1877077..2168484c84e29 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -152,7 +152,7 @@ pub fn header_kind(doc: doc::ItemTag) -> ~str { ~"Function" } doc::ConstTag(_) => { - ~"Const" + ~"Freeze" } doc::EnumTag(_) => { ~"Enum" @@ -793,7 +793,7 @@ mod test { #[test] fn should_write_const_header() { let markdown = render(~"static a: bool = true;"); - assert!(markdown.contains("## Const `a`\n\n")); + assert!(markdown.contains("## Freeze `a`\n\n")); } #[test] diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs index 266dd1a35e32c..60887d9dd6dd7 100644 --- a/src/libstd/clone.rs +++ b/src/libstd/clone.rs @@ -22,7 +22,7 @@ by convention implementing the `Clone` trait and calling the */ -use core::kinds::Const; +use core::kinds::Freeze; /// A common trait for cloning an object. pub trait Clone { @@ -101,16 +101,16 @@ impl DeepClone for ~T { } // FIXME: #6525: should also be implemented for `T: Owned + DeepClone` -impl DeepClone for @T { - /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing +impl DeepClone for @T { + /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing /// a deep clone of a potentially cyclical type. #[inline(always)] fn deep_clone(&self) -> @T { @(**self).deep_clone() } } // FIXME: #6525: should also be implemented for `T: Owned + DeepClone` -impl DeepClone for @mut T { - /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing +impl DeepClone for @mut T { + /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing /// a deep clone of a potentially cyclical type. #[inline(always)] fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() } diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index b7ec90574e29d..9d5348ff98f0a 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -57,13 +57,13 @@ pub trait Owned { #[cfg(stage0)] #[lang="const"] -pub trait Const { +pub trait Freeze { // empty. } #[cfg(not(stage0))] #[lang="freeze"] -pub trait Const { +pub trait Freeze { // empty. } diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index efa40430e3cad..eb16f5d776cd9 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -30,7 +30,7 @@ Rust's prelude has three main parts: // Reexported core operators pub use either::{Either, Left, Right}; pub use kinds::{Copy, Sized}; -pub use kinds::{Const, Owned}; +pub use kinds::{Freeze, Owned}; pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Drop}; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e3182916723b7..aec9d2bd5b534 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -149,7 +149,7 @@ pub static crate_node_id: node_id = 0; // The AST represents all type param bounds as types. // typeck::collect::compute_bounds matches these against // the "special" built-in traits (see middle::lang_items) and -// detects Copy, Send, Owned, and Const. +// detects Copy, Send, Owned, and Freeze. pub enum TyParamBound { TraitTyParamBound(@trait_ref), RegionTyParamBound diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 47c0827eb23c4..c757d0b04fb8a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1132,14 +1132,14 @@ impl Parser { pub fn token_is_mutability(&self, tok: &token::Token) -> bool { token::is_keyword(keywords::Mut, tok) || - token::is_keyword(keywords::Const, tok) + token::is_keyword(keywords::Freeze, tok) } // parse mutability declaration (mut/const/imm) pub fn parse_mutability(&self) -> mutability { if self.eat_keyword(keywords::Mut) { m_mutbl - } else if self.eat_keyword(keywords::Const) { + } else if self.eat_keyword(keywords::Freeze) { m_const } else { m_imm @@ -3032,7 +3032,7 @@ impl Parser { ) -> ast::explicit_self_ { // We need to make sure it isn't a mode or a type if token::is_keyword(keywords::Self, &p.look_ahead(1)) || - ((token::is_keyword(keywords::Const, &p.look_ahead(1)) || + ((token::is_keyword(keywords::Freeze, &p.look_ahead(1)) || token::is_keyword(keywords::Mut, &p.look_ahead(1))) && token::is_keyword(keywords::Self, &p.look_ahead(2))) { @@ -3667,7 +3667,7 @@ impl Parser { let lo = self.span.lo; // XXX: Obsolete; remove after snap. - if self.eat_keyword(keywords::Const) { + if self.eat_keyword(keywords::Freeze) { self.obsolete(*self.last_span, ObsoleteConstItem); } else { self.expect_keyword(keywords::Static); @@ -4054,11 +4054,11 @@ impl Parser { } } // the rest are all guaranteed to be items: - if (self.is_keyword(keywords::Const) || + if (self.is_keyword(keywords::Freeze) || (self.is_keyword(keywords::Static) && !token::is_keyword(keywords::Fn, &self.look_ahead(1)))) { // CONST / STATIC ITEM - if self.is_keyword(keywords::Const) { + if self.is_keyword(keywords::Freeze) { self.obsolete(*self.span, ObsoleteConstItem); } self.bump(); @@ -4156,7 +4156,7 @@ impl Parser { let visibility = self.parse_visibility(); - if (self.is_keyword(keywords::Const) || self.is_keyword(keywords::Static)) { + if (self.is_keyword(keywords::Freeze) || self.is_keyword(keywords::Static)) { // FOREIGN CONST ITEM let item = self.parse_item_foreign_const(visibility, attrs); return iovi_foreign_item(item); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index e7bc67340f011..2436e0e5c69bb 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -573,7 +573,7 @@ pub mod keywords { // Strict keywords As, Break, - Const, + Freeze, Copy, Do, Else, @@ -614,42 +614,42 @@ pub mod keywords { impl Keyword { pub fn to_ident(&self) -> ident { match *self { - As => ident { name: 35, ctxt: 0 }, - Break => ident { name: 36, ctxt: 0 }, - Const => ident { name: 37, ctxt: 0 }, - Copy => ident { name: 38, ctxt: 0 }, - Do => ident { name: 39, ctxt: 0 }, - Else => ident { name: 41, ctxt: 0 }, - Enum => ident { name: 42, ctxt: 0 }, - Extern => ident { name: 43, ctxt: 0 }, - False => ident { name: 44, ctxt: 0 }, - Fn => ident { name: 45, ctxt: 0 }, - For => ident { name: 46, ctxt: 0 }, - If => ident { name: 47, ctxt: 0 }, - Impl => ident { name: 48, ctxt: 0 }, - Let => ident { name: 49, ctxt: 0 }, - __Log => ident { name: 50, ctxt: 0 }, - Loop => ident { name: 51, ctxt: 0 }, - Match => ident { name: 52, ctxt: 0 }, - Mod => ident { name: 53, ctxt: 0 }, - Mut => ident { name: 54, ctxt: 0 }, - Once => ident { name: 55, ctxt: 0 }, - Priv => ident { name: 56, ctxt: 0 }, - Pub => ident { name: 57, ctxt: 0 }, - Pure => ident { name: 58, ctxt: 0 }, - Ref => ident { name: 59, ctxt: 0 }, - Return => ident { name: 60, ctxt: 0 }, - Static => ident { name: 29, ctxt: 0 }, - Self => ident { name: 8, ctxt: 0 }, - Struct => ident { name: 61, ctxt: 0 }, - Super => ident { name: 62, ctxt: 0 }, - True => ident { name: 63, ctxt: 0 }, - Trait => ident { name: 64, ctxt: 0 }, - Type => ident { name: 65, ctxt: 0 }, - Unsafe => ident { name: 66, ctxt: 0 }, - Use => ident { name: 67, ctxt: 0 }, - While => ident { name: 68, ctxt: 0 }, - Be => ident { name: 69, ctxt: 0 }, + As => ident { repr: 35, ctxt: 0 }, + Break => ident { repr: 36, ctxt: 0 }, + Freeze => ident { repr: 37, ctxt: 0 }, + Copy => ident { repr: 38, ctxt: 0 }, + Do => ident { repr: 39, ctxt: 0 }, + Else => ident { repr: 41, ctxt: 0 }, + Enum => ident { repr: 42, ctxt: 0 }, + Extern => ident { repr: 43, ctxt: 0 }, + False => ident { repr: 44, ctxt: 0 }, + Fn => ident { repr: 45, ctxt: 0 }, + For => ident { repr: 46, ctxt: 0 }, + If => ident { repr: 47, ctxt: 0 }, + Impl => ident { repr: 48, ctxt: 0 }, + Let => ident { repr: 49, ctxt: 0 }, + __Log => ident { repr: 50, ctxt: 0 }, + Loop => ident { repr: 51, ctxt: 0 }, + Match => ident { repr: 52, ctxt: 0 }, + Mod => ident { repr: 53, ctxt: 0 }, + Mut => ident { repr: 54, ctxt: 0 }, + Once => ident { repr: 55, ctxt: 0 }, + Priv => ident { repr: 56, ctxt: 0 }, + Pub => ident { repr: 57, ctxt: 0 }, + Pure => ident { repr: 58, ctxt: 0 }, + Ref => ident { repr: 59, ctxt: 0 }, + Return => ident { repr: 60, ctxt: 0 }, + Static => ident { repr: 29, ctxt: 0 }, + Self => ident { repr: 8, ctxt: 0 }, + Struct => ident { repr: 61, ctxt: 0 }, + Super => ident { repr: 62, ctxt: 0 }, + True => ident { repr: 63, ctxt: 0 }, + Trait => ident { repr: 64, ctxt: 0 }, + Type => ident { repr: 65, ctxt: 0 }, + Unsafe => ident { repr: 66, ctxt: 0 }, + Use => ident { repr: 67, ctxt: 0 }, + While => ident { repr: 68, ctxt: 0 }, + Be => ident { repr: 69, ctxt: 0 }, } } } diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index d4f183ada7b6e..b62ef6bbe7016 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -26,7 +26,7 @@ pub struct Interner { } // when traits can extend traits, we should extend index to get [] -impl Interner { +impl Interner { pub fn new() -> Interner { Interner { map: @mut HashMap::new(), diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index bbc0f1ad3e558..a9250630ad496 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -20,17 +20,17 @@ struct arc_destruct { } #[unsafe_destructor] -impl Drop for arc_destruct { +impl Drop for arc_destruct { fn finalize(&self) {} } -fn arc_destruct(data: int) -> arc_destruct { +fn arc_destruct(data: int) -> arc_destruct { arc_destruct { _data: data } } -fn arc(_data: T) -> arc_destruct { +fn arc(_data: T) -> arc_destruct { arc_destruct(0) } diff --git a/src/test/compile-fail/issue-2611-4.rs b/src/test/compile-fail/issue-2611-4.rs index 2385be5723e2a..531d4eab53578 100644 --- a/src/test/compile-fail/issue-2611-4.rs +++ b/src/test/compile-fail/issue-2611-4.rs @@ -20,7 +20,7 @@ struct E { } impl A for E { - fn b(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Const` + fn b(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Freeze` } fn main() {} diff --git a/src/test/compile-fail/issue-3177-mutable-struct.rs b/src/test/compile-fail/issue-3177-mutable-struct.rs index 31c0dc7d9c4e2..180f13d037195 100644 --- a/src/test/compile-fail/issue-3177-mutable-struct.rs +++ b/src/test/compile-fail/issue-3177-mutable-struct.rs @@ -10,7 +10,7 @@ // xfail-test // error-pattern: instantiating a type parameter with an incompatible type -struct S { +struct S { s: T, cant_nest: () } diff --git a/src/test/compile-fail/mutable-enum.rs b/src/test/compile-fail/mutable-enum.rs index 2368e5eb5c51f..db2172b2e570f 100644 --- a/src/test/compile-fail/mutable-enum.rs +++ b/src/test/compile-fail/mutable-enum.rs @@ -11,9 +11,9 @@ #[mutable] enum Foo { A } -fn bar(_: T) {} +fn bar(_: T) {} fn main() { let x = A; - bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Const` + bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Freeze` } diff --git a/src/test/compile-fail/mutable-struct.rs b/src/test/compile-fail/mutable-struct.rs index ee040506c40bd..8511bcdcd3501 100644 --- a/src/test/compile-fail/mutable-struct.rs +++ b/src/test/compile-fail/mutable-struct.rs @@ -11,9 +11,9 @@ #[mutable] struct Foo { a: int } -fn bar(_: T) {} +fn bar(_: T) {} fn main() { let x = Foo { a: 5 }; - bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Const` + bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Freeze` } diff --git a/src/test/run-pass/const-bound.rs b/src/test/run-pass/const-bound.rs index 685d86c740d97..05f586f76e950 100644 --- a/src/test/run-pass/const-bound.rs +++ b/src/test/run-pass/const-bound.rs @@ -12,7 +12,7 @@ // are const. -fn foo(x: T) -> T { x } +fn foo(x: T) -> T { x } struct F { field: int } diff --git a/src/test/run-pass/issue-2611-3.rs b/src/test/run-pass/issue-2611-3.rs index acc6ffd0dd1b3..7f6535526312a 100644 --- a/src/test/run-pass/issue-2611-3.rs +++ b/src/test/run-pass/issue-2611-3.rs @@ -12,7 +12,7 @@ // than the traits require. trait A { - fn b(x: C) -> C; + fn b(x: C) -> C; } struct E { From 537e62ed7353a2d1defd9883afb15a6f8d459ba0 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Jun 2013 17:56:24 -0700 Subject: [PATCH 04/13] librustc: Change "Owned" to "Send" everywhere --- src/libextra/arc.rs | 28 ++--- src/libextra/comm.rs | 14 +-- src/libextra/flatpipes.rs | 24 ++--- src/libextra/future.rs | 4 +- src/libextra/par.rs | 10 +- src/libextra/rc.rs | 8 +- src/libextra/sync.rs | 6 +- src/libextra/timer.rs | 4 +- src/libextra/workcache.rs | 10 +- src/librustc/middle/borrowck/doc.rs | 4 +- .../middle/borrowck/gather_loans/lifetime.rs | 2 +- .../borrowck/gather_loans/restrictions.rs | 2 +- src/librustc/middle/typeck/check/_match.rs | 8 +- src/librustdoc/astsrv.rs | 2 +- src/librustdoc/attr_pass.rs | 2 +- src/libstd/clone.rs | 4 +- src/libstd/comm.rs | 100 +++++++++--------- src/libstd/kinds.rs | 6 +- src/libstd/pipes.rs | 34 +++--- src/libstd/prelude.rs | 2 +- src/libstd/rt/comm.rs | 10 +- src/libstd/rt/message_queue.rs | 4 +- src/libstd/rt/work_queue.rs | 4 +- src/libstd/task/mod.rs | 8 +- src/libstd/unstable/global.rs | 14 +-- src/libstd/unstable/sync.rs | 12 +-- src/libsyntax/ast.rs | 2 +- src/libsyntax/ext/deriving/to_str.rs | 2 +- src/libsyntax/ext/deriving/ty.rs | 6 +- src/test/auxiliary/cci_capture_clause.rs | 2 +- src/test/bench/pingpong.rs | 6 +- .../compile-fail/closure-bounds-subtype.rs | 14 +-- src/test/compile-fail/issue-2766-a.rs | 6 +- .../compile-fail/kindck-destructor-owned.rs | 2 +- .../compile-fail/liveness-use-after-send.rs | 2 +- src/test/compile-fail/non_owned-enum.rs | 4 +- src/test/compile-fail/non_owned-struct.rs | 4 +- src/test/compile-fail/unique-unique-kind.rs | 4 +- src/test/compile-fail/unsendable-class.rs | 4 +- src/test/run-fail/bug-811.rs | 2 +- src/test/run-pass/alignment-gep-tup-like-2.rs | 2 +- src/test/run-pass/fixed-point-bind-unique.rs | 4 +- src/test/run-pass/fn-bare-spawn.rs | 2 +- src/test/run-pass/generic-alias-unique.rs | 2 +- src/test/run-pass/issue-2718.rs | 24 ++--- src/test/run-pass/issue-2834.rs | 2 +- src/test/run-pass/issue-2930.rs | 2 +- src/test/run-pass/pipe-bank-proto.rs | 2 +- src/test/run-pass/pipe-select.rs | 4 +- src/test/run-pass/pipe-sleep.rs | 2 +- src/test/run-pass/send-type-inference.rs | 2 +- src/test/run-pass/type-param-constraints.rs | 2 +- src/test/run-pass/uniq-cc-generic.rs | 2 +- src/test/run-pass/unique-kinds.rs | 4 +- 54 files changed, 221 insertions(+), 221 deletions(-) diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs index 4c5f90e0dfbed..c7a1a756617cc 100644 --- a/src/libextra/arc.rs +++ b/src/libextra/arc.rs @@ -112,7 +112,7 @@ impl<'self> Condvar<'self> { pub struct ARC { x: UnsafeAtomicRcBox } /// Create an atomically reference counted wrapper. -pub fn ARC(data: T) -> ARC { +pub fn ARC(data: T) -> ARC { ARC { x: UnsafeAtomicRcBox::new(data) } } @@ -120,7 +120,7 @@ pub fn ARC(data: T) -> ARC { * Access the underlying data in an atomically reference counted * wrapper. */ -impl ARC { +impl ARC { pub fn get<'a>(&'a self) -> &'a T { unsafe { &*self.x.get_immut() } } @@ -133,7 +133,7 @@ impl ARC { * object. However, one of the `arc` objects can be sent to another task, * allowing them to share the underlying data. */ -impl Clone for ARC { +impl Clone for ARC { fn clone(&self) -> ARC { ARC { x: self.x.clone() } } @@ -149,14 +149,14 @@ struct MutexARCInner { lock: Mutex, failed: bool, data: T } struct MutexARC { x: UnsafeAtomicRcBox> } /// Create a mutex-protected ARC with the supplied data. -pub fn MutexARC(user_data: T) -> MutexARC { +pub fn MutexARC(user_data: T) -> MutexARC { mutex_arc_with_condvars(user_data, 1) } /** * Create a mutex-protected ARC with the supplied data and a specified number * of condvars (as sync::mutex_with_condvars). */ -pub fn mutex_arc_with_condvars(user_data: T, +pub fn mutex_arc_with_condvars(user_data: T, num_condvars: uint) -> MutexARC { let data = MutexARCInner { lock: mutex_with_condvars(num_condvars), @@ -164,7 +164,7 @@ pub fn mutex_arc_with_condvars(user_data: T, MutexARC { x: UnsafeAtomicRcBox::new(data) } } -impl Clone for MutexARC { +impl Clone for MutexARC { /// Duplicate a mutex-protected ARC, as arc::clone. fn clone(&self) -> MutexARC { // NB: Cloning the underlying mutex is not necessary. Its reference @@ -173,7 +173,7 @@ impl Clone for MutexARC { } } -impl MutexARC { +impl MutexARC { /** * Access the underlying mutable data with mutual exclusion from other @@ -285,14 +285,14 @@ struct RWARC { } /// Create a reader/writer ARC with the supplied data. -pub fn RWARC(user_data: T) -> RWARC { +pub fn RWARC(user_data: T) -> RWARC { rw_arc_with_condvars(user_data, 1) } /** * Create a reader/writer ARC with the supplied data and a specified number * of condvars (as sync::rwlock_with_condvars). */ -pub fn rw_arc_with_condvars( +pub fn rw_arc_with_condvars( user_data: T, num_condvars: uint) -> RWARC { @@ -302,7 +302,7 @@ pub fn rw_arc_with_condvars( RWARC { x: UnsafeAtomicRcBox::new(data), cant_nest: () } } -impl RWARC { +impl RWARC { /// Duplicate a rwlock-protected ARC, as arc::clone. pub fn clone(&self) -> RWARC { RWARC { @@ -313,7 +313,7 @@ impl RWARC { } -impl RWARC { +impl RWARC { /** * Access the underlying data mutably. Locks the rwlock in write mode; * other readers and writers will block. @@ -439,7 +439,7 @@ impl RWARC { // lock it. This wraps the unsafety, with the justification that the 'lock' // field is never overwritten; only 'failed' and 'data'. #[doc(hidden)] -fn borrow_rwlock(state: *const RWARCInner) -> *RWlock { +fn borrow_rwlock(state: *const RWARCInner) -> *RWlock { unsafe { cast::transmute(&const (*state).lock) } } @@ -456,7 +456,7 @@ pub struct RWReadMode<'self, T> { token: sync::RWlockReadMode<'self>, } -impl<'self, T:Freeze + Owned> RWWriteMode<'self, T> { +impl<'self, T:Freeze + Send> RWWriteMode<'self, T> { /// Access the pre-downgrade RWARC in write mode. pub fn write(&mut self, blk: &fn(x: &mut T) -> U) -> U { match *self { @@ -497,7 +497,7 @@ impl<'self, T:Freeze + Owned> RWWriteMode<'self, T> { } } -impl<'self, T:Freeze + Owned> RWReadMode<'self, T> { +impl<'self, T:Freeze + Send> RWReadMode<'self, T> { /// Access the post-downgrade rwlock in read mode. pub fn read(&self, blk: &fn(x: &T) -> U) -> U { match *self { diff --git a/src/libextra/comm.rs b/src/libextra/comm.rs index 1001d4f6ac9ed..2cb2128db5f73 100644 --- a/src/libextra/comm.rs +++ b/src/libextra/comm.rs @@ -30,7 +30,7 @@ pub struct DuplexStream { } // Allow these methods to be used without import: -impl DuplexStream { +impl DuplexStream { pub fn send(&self, x: T) { self.chan.send(x) } @@ -48,19 +48,19 @@ impl DuplexStream { } } -impl GenericChan for DuplexStream { +impl GenericChan for DuplexStream { fn send(&self, x: T) { self.chan.send(x) } } -impl GenericSmartChan for DuplexStream { +impl GenericSmartChan for DuplexStream { fn try_send(&self, x: T) -> bool { self.chan.try_send(x) } } -impl GenericPort for DuplexStream { +impl GenericPort for DuplexStream { fn recv(&self) -> U { self.port.recv() } @@ -70,20 +70,20 @@ impl GenericPort for DuplexStream { } } -impl Peekable for DuplexStream { +impl Peekable for DuplexStream { fn peek(&self) -> bool { self.port.peek() } } -impl Selectable for DuplexStream { +impl Selectable for DuplexStream { fn header(&mut self) -> *mut pipes::PacketHeader { self.port.header() } } /// Creates a bidirectional stream. -pub fn DuplexStream() +pub fn DuplexStream() -> (DuplexStream, DuplexStream) { let (p1, c2) = comm::stream(); diff --git a/src/libextra/flatpipes.rs b/src/libextra/flatpipes.rs index c0f619c1b858d..794ace5908635 100644 --- a/src/libextra/flatpipes.rs +++ b/src/libextra/flatpipes.rs @@ -166,8 +166,8 @@ Constructors for flat pipes that send POD types using memcpy. # Safety Note -This module is currently unsafe because it uses `Copy Owned` as a type -parameter bounds meaning POD (plain old data), but `Copy Owned` and +This module is currently unsafe because it uses `Copy Send` as a type +parameter bounds meaning POD (plain old data), but `Copy Send` and POD are not equivelant. */ @@ -191,7 +191,7 @@ pub mod pod { pub type PipeChan = FlatChan, PipeByteChan>; /// Create a `FlatPort` from a `Reader` - pub fn reader_port( + pub fn reader_port( reader: R ) -> ReaderPort { let unflat: PodUnflattener = PodUnflattener::new(); @@ -200,7 +200,7 @@ pub mod pod { } /// Create a `FlatChan` from a `Writer` - pub fn writer_chan( + pub fn writer_chan( writer: W ) -> WriterChan { let flat: PodFlattener = PodFlattener::new(); @@ -209,21 +209,21 @@ pub mod pod { } /// Create a `FlatPort` from a `Port<~[u8]>` - pub fn pipe_port(port: Port<~[u8]>) -> PipePort { + pub fn pipe_port(port: Port<~[u8]>) -> PipePort { let unflat: PodUnflattener = PodUnflattener::new(); let byte_port = PipeBytePort::new(port); FlatPort::new(unflat, byte_port) } /// Create a `FlatChan` from a `Chan<~[u8]>` - pub fn pipe_chan(chan: Chan<~[u8]>) -> PipeChan { + pub fn pipe_chan(chan: Chan<~[u8]>) -> PipeChan { let flat: PodFlattener = PodFlattener::new(); let byte_chan = PipeByteChan::new(chan); FlatChan::new(flat, byte_chan) } /// Create a pair of `FlatChan` and `FlatPort`, backed by pipes - pub fn pipe_stream() -> (PipePort, PipeChan) { + pub fn pipe_stream() -> (PipePort, PipeChan) { let (port, chan) = comm::stream(); return (pipe_port(port), pipe_chan(chan)); } @@ -352,7 +352,7 @@ pub mod flatteners { use core::sys::size_of; use core::vec; - // FIXME #4074: Copy + Owned != POD + // FIXME #4074: Copy + Send != POD pub struct PodUnflattener { bogus: () } @@ -361,7 +361,7 @@ pub mod flatteners { bogus: () } - impl Unflattener for PodUnflattener { + impl Unflattener for PodUnflattener { fn unflatten(&self, buf: ~[u8]) -> T { assert!(size_of::() != 0); assert_eq!(size_of::(), buf.len()); @@ -371,7 +371,7 @@ pub mod flatteners { } } - impl Flattener for PodFlattener { + impl Flattener for PodFlattener { fn flatten(&self, val: T) -> ~[u8] { assert!(size_of::() != 0); let val: *T = ptr::to_unsafe_ptr(&val); @@ -380,7 +380,7 @@ pub mod flatteners { } } - impl PodUnflattener { + impl PodUnflattener { pub fn new() -> PodUnflattener { PodUnflattener { bogus: () @@ -388,7 +388,7 @@ pub mod flatteners { } } - impl PodFlattener { + impl PodFlattener { pub fn new() -> PodFlattener { PodFlattener { bogus: () diff --git a/src/libextra/future.rs b/src/libextra/future.rs index 40cfeebd5dcd8..c231c8b0090a3 100644 --- a/src/libextra/future.rs +++ b/src/libextra/future.rs @@ -101,7 +101,7 @@ pub fn from_value(val: A) -> Future { Future {state: Forced(val)} } -pub fn from_port(port: PortOne) -> Future { +pub fn from_port(port: PortOne) -> Future { /*! * Create a future from a port * @@ -127,7 +127,7 @@ pub fn from_fn(f: ~fn() -> A) -> Future { Future {state: Pending(f)} } -pub fn spawn(blk: ~fn() -> A) -> Future { +pub fn spawn(blk: ~fn() -> A) -> Future { /*! * Create a future from a unique closure. * diff --git a/src/libextra/par.rs b/src/libextra/par.rs index 05fe4ed72ee8e..08b81b413f8d4 100644 --- a/src/libextra/par.rs +++ b/src/libextra/par.rs @@ -34,7 +34,7 @@ static min_granularity : uint = 1024u; * This is used to build most of the other parallel vector functions, * like map or alli. */ -fn map_slices( +fn map_slices( xs: &[A], f: &fn() -> ~fn(uint, v: &[A]) -> B) -> ~[B] { @@ -89,7 +89,7 @@ fn map_slices( } /// A parallel version of map. -pub fn map( +pub fn map( xs: &[A], fn_factory: &fn() -> ~fn(&A) -> B) -> ~[B] { vec::concat(map_slices(xs, || { let f = fn_factory(); @@ -100,7 +100,7 @@ pub fn map( } /// A parallel version of mapi. -pub fn mapi( +pub fn mapi( xs: &[A], fn_factory: &fn() -> ~fn(uint, &A) -> B) -> ~[B] { let slices = map_slices(xs, || { @@ -119,7 +119,7 @@ pub fn mapi( } /// Returns true if the function holds for all elements in the vector. -pub fn alli( +pub fn alli( xs: &[A], fn_factory: &fn() -> ~fn(uint, &A) -> bool) -> bool { @@ -134,7 +134,7 @@ pub fn alli( } /// Returns true if the function holds for any elements in the vector. -pub fn any( +pub fn any( xs: &[A], fn_factory: &fn() -> ~fn(&A) -> bool) -> bool { let mapped = map_slices(xs, || { diff --git a/src/libextra/rc.rs b/src/libextra/rc.rs index e72939b0a2053..e165bfa4ab697 100644 --- a/src/libextra/rc.rs +++ b/src/libextra/rc.rs @@ -13,10 +13,10 @@ /** Task-local reference counted smart pointers Task-local reference counted smart pointers are an alternative to managed boxes with deterministic -destruction. They are restricted to containing types that are either `Owned` or `Freeze` (or both) to +destruction. They are restricted to containing types that are either `Send` or `Freeze` (or both) to prevent cycles. -Neither `Rc` or `RcMut` is ever `Owned` and `RcMut` is never `Freeze`. If `T` is `Freeze`, a +Neither `Rc` or `RcMut` is ever `Send` and `RcMut` is never `Freeze`. If `T` is `Freeze`, a cycle cannot be created with `Rc` because there is no way to modify it after creation. */ @@ -51,7 +51,7 @@ impl Rc { } // FIXME: #6516: should be a static method -pub fn rc_from_owned(value: T) -> Rc { +pub fn rc_from_owned(value: T) -> Rc { unsafe { Rc::new(value) } } @@ -182,7 +182,7 @@ impl RcMut { } // FIXME: #6516: should be a static method -pub fn rc_mut_from_owned(value: T) -> RcMut { +pub fn rc_mut_from_owned(value: T) -> RcMut { unsafe { RcMut::new(value) } } diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs index 8bbe0afa704e1..6d2932057f00a 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -84,7 +84,7 @@ struct SemInner { struct Sem(Exclusive>); #[doc(hidden)] -fn new_sem(count: int, q: Q) -> Sem { +fn new_sem(count: int, q: Q) -> Sem { Sem(exclusive(SemInner { count: count, waiters: new_waitqueue(), blocked: q })) } @@ -99,7 +99,7 @@ fn new_sem_and_signal(count: int, num_condvars: uint) } #[doc(hidden)] -impl Sem { +impl Sem { pub fn acquire(&self) { unsafe { let mut waiter_nobe = None; @@ -170,7 +170,7 @@ type SemAndSignalRelease<'self> = SemReleaseGeneric<'self, ~[Waitqueue]>; struct SemReleaseGeneric<'self, Q> { sem: &'self Sem } #[unsafe_destructor] -impl<'self, Q:Owned> Drop for SemReleaseGeneric<'self, Q> { +impl<'self, Q:Send> Drop for SemReleaseGeneric<'self, Q> { fn finalize(&self) { self.sem.release(); } diff --git a/src/libextra/timer.rs b/src/libextra/timer.rs index 7a4ad34b50892..bf548c9e408e4 100644 --- a/src/libextra/timer.rs +++ b/src/libextra/timer.rs @@ -39,7 +39,7 @@ use core::libc; * * ch - a channel of type T to send a `val` on * * val - a value of type T to send over the provided `ch` */ -pub fn delayed_send(iotask: &IoTask, +pub fn delayed_send(iotask: &IoTask, msecs: uint, ch: &Chan, val: T) { @@ -119,7 +119,7 @@ pub fn sleep(iotask: &IoTask, msecs: uint) { * on the provided port in the allotted timeout period, then the result will * be a `Some(T)`. If not, then `None` will be returned. */ -pub fn recv_timeout(iotask: &IoTask, +pub fn recv_timeout(iotask: &IoTask, msecs: uint, wait_po: &Port) -> Option { diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs index b2fd998b73fd2..0953aa5be8115 100644 --- a/src/libextra/workcache.rs +++ b/src/libextra/workcache.rs @@ -271,7 +271,7 @@ impl Context { } } - pub fn prep + Decodable>(@self, // FIXME(#5121) fn_name:&str, @@ -291,7 +291,7 @@ trait TPrep { fn declare_input(&mut self, kind:&str, name:&str, val:&str); fn is_fresh(&self, cat:&str, kind:&str, name:&str, val:&str) -> bool; fn all_fresh(&self, cat:&str, map:&WorkMap) -> bool; - fn exec + Decodable>( // FIXME(#5121) &self, blk: ~fn(&Exec) -> T) -> Work; @@ -327,7 +327,7 @@ impl TPrep for Prep { return true; } - fn exec + Decodable>( // FIXME(#5121) &self, blk: ~fn(&Exec) -> T) -> Work { @@ -364,7 +364,7 @@ impl TPrep for Prep { } } -impl + Decodable> Work { // FIXME(#5121) pub fn new(p: @mut Prep, e: Either>) -> Work { @@ -373,7 +373,7 @@ impl + Decodable>( // FIXME(#5121) w: Work) -> T { diff --git a/src/librustc/middle/borrowck/doc.rs b/src/librustc/middle/borrowck/doc.rs index 7a91f204b1312..8bb5c4620ef78 100644 --- a/src/librustc/middle/borrowck/doc.rs +++ b/src/librustc/middle/borrowck/doc.rs @@ -359,7 +359,7 @@ of its owner: LIFETIME(LV.f, LT, MQ) // L-Field LIFETIME(LV, LT, MQ) - LIFETIME(*LV, LT, MQ) // L-Deref-Owned + LIFETIME(*LV, LT, MQ) // L-Deref-Send TYPE(LV) = ~Ty LIFETIME(LV, LT, MQ) @@ -504,7 +504,7 @@ must prevent the owned pointer `LV` from being mutated, which means that we always add `MUTATE` and `CLAIM` to the restriction set imposed on `LV`: - RESTRICTIONS(*LV, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Owned-Pointer + RESTRICTIONS(*LV, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer TYPE(LV) = ~Ty RESTRICTIONS(LV, ACTIONS|MUTATE|CLAIM) = RS diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index 9455340268eff..131ee5aa067b4 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -109,7 +109,7 @@ impl GuaranteeLifetimeContext { } mc::cat_downcast(base) | - mc::cat_deref(base, _, mc::uniq_ptr(*)) | // L-Deref-Owned + mc::cat_deref(base, _, mc::uniq_ptr(*)) | // L-Deref-Send mc::cat_interior(base, _) => { // L-Field self.check(base, discr_scope) } diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index f54cfb3d1d4ed..659b69f0cf55a 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -103,7 +103,7 @@ impl RestrictionsContext { } mc::cat_deref(cmt_base, _, mc::uniq_ptr(*)) => { - // R-Deref-Owned-Pointer + // R-Deref-Send-Pointer // // When we borrow the interior of an owned pointer, we // cannot permit the base to be mutated, because that diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 4a546ce20d2d1..87708e46e6388 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -539,7 +539,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { check_pointer_pat(pcx, Managed, inner, pat.id, pat.span, expected); } ast::pat_uniq(inner) => { - check_pointer_pat(pcx, Owned, inner, pat.id, pat.span, expected); + check_pointer_pat(pcx, Send, inner, pat.id, pat.span, expected); } ast::pat_region(inner) => { check_pointer_pat(pcx, Borrowed, inner, pat.id, pat.span, expected); @@ -625,7 +625,7 @@ pub fn check_pointer_pat(pcx: &pat_ctxt, ty::ty_box(e_inner) if pointer_kind == Managed => { check_inner(e_inner); } - ty::ty_uniq(e_inner) if pointer_kind == Owned => { + ty::ty_uniq(e_inner) if pointer_kind == Send => { check_inner(e_inner); } ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => { @@ -642,7 +642,7 @@ pub fn check_pointer_pat(pcx: &pat_ctxt, Some(expected), fmt!("%s pattern", match pointer_kind { Managed => "an @-box", - Owned => "a ~-box", + Send => "a ~-box", Borrowed => "an &-pointer" }), None); @@ -652,4 +652,4 @@ pub fn check_pointer_pat(pcx: &pat_ctxt, } #[deriving(Eq)] -enum PointerKind { Managed, Owned, Borrowed } +enum PointerKind { Managed, Send, Borrowed } diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs index 9d8f750a35006..ccb9acd10d724 100644 --- a/src/librustdoc/astsrv.rs +++ b/src/librustdoc/astsrv.rs @@ -101,7 +101,7 @@ fn act(po: &Port, source: @str, parse: Parser) { } } -pub fn exec( +pub fn exec( srv: Srv, f: ~fn(ctxt: Ctxt) -> T ) -> T { diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs index a1dad7d17f8e8..ae8f109d697f7 100644 --- a/src/librustdoc/attr_pass.rs +++ b/src/librustdoc/attr_pass.rs @@ -101,7 +101,7 @@ fn fold_item( } } -fn parse_item_attrs( +fn parse_item_attrs( srv: astsrv::Srv, id: doc::AstId, parse_attrs: ~fn(a: ~[ast::attribute]) -> T) -> T { diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs index 60887d9dd6dd7..b3b47858c9295 100644 --- a/src/libstd/clone.rs +++ b/src/libstd/clone.rs @@ -100,7 +100,7 @@ impl DeepClone for ~T { fn deep_clone(&self) -> ~T { ~(**self).deep_clone() } } -// FIXME: #6525: should also be implemented for `T: Owned + DeepClone` +// FIXME: #6525: should also be implemented for `T: Send + DeepClone` impl DeepClone for @T { /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing /// a deep clone of a potentially cyclical type. @@ -108,7 +108,7 @@ impl DeepClone for @T { fn deep_clone(&self) -> @T { @(**self).deep_clone() } } -// FIXME: #6525: should also be implemented for `T: Owned + DeepClone` +// FIXME: #6525: should also be implemented for `T: Send + DeepClone` impl DeepClone for @mut T { /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing /// a deep clone of a potentially cyclical type. diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index f0c353c8d62b6..dd2ed2c953653 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -17,7 +17,7 @@ Message passing use cast::{transmute, transmute_mut}; use container::Container; use either::{Either, Left, Right}; -use kinds::Owned; +use kinds::Send; use option::{Option, Some, None}; use uint; use vec; @@ -78,7 +78,7 @@ pub struct Port { These allow sending or receiving an unlimited number of messages. */ -pub fn stream() -> (Port, Chan) { +pub fn stream() -> (Port, Chan) { let (port, chan) = match rt::context() { rt::OldTaskContext => match pipesy::stream() { (p, c) => (Left(p), Left(c)) @@ -92,7 +92,7 @@ pub fn stream() -> (Port, Chan) { return (port, chan); } -impl GenericChan for Chan { +impl GenericChan for Chan { fn send(&self, x: T) { match self.inner { Left(ref chan) => chan.send(x), @@ -101,7 +101,7 @@ impl GenericChan for Chan { } } -impl GenericSmartChan for Chan { +impl GenericSmartChan for Chan { fn try_send(&self, x: T) -> bool { match self.inner { Left(ref chan) => chan.try_send(x), @@ -110,7 +110,7 @@ impl GenericSmartChan for Chan { } } -impl GenericPort for Port { +impl GenericPort for Port { fn recv(&self) -> T { match self.inner { Left(ref port) => port.recv(), @@ -126,7 +126,7 @@ impl GenericPort for Port { } } -impl Peekable for Port { +impl Peekable for Port { fn peek(&self) -> bool { match self.inner { Left(ref port) => port.peek(), @@ -135,7 +135,7 @@ impl Peekable for Port { } } -impl Selectable for Port { +impl Selectable for Port { fn header(&mut self) -> *mut PacketHeader { match self.inner { Left(ref mut port) => port.header(), @@ -150,7 +150,7 @@ pub struct PortSet { ports: ~[pipesy::Port], } -impl PortSet { +impl PortSet { pub fn new() -> PortSet { PortSet { ports: ~[] @@ -176,7 +176,7 @@ impl PortSet { } } -impl GenericPort for PortSet { +impl GenericPort for PortSet { fn try_recv(&self) -> Option { unsafe { let self_ports = transmute_mut(&self.ports); @@ -205,7 +205,7 @@ impl GenericPort for PortSet { } } -impl Peekable for PortSet { +impl Peekable for PortSet { fn peek(&self) -> bool { // It'd be nice to use self.port.each, but that version isn't // pure. @@ -224,7 +224,7 @@ pub struct SharedChan { ch: Exclusive> } -impl SharedChan { +impl SharedChan { /// Converts a `chan` into a `shared_chan`. pub fn new(c: Chan) -> SharedChan { let Chan { inner } = c; @@ -236,7 +236,7 @@ impl SharedChan { } } -impl GenericChan for SharedChan { +impl GenericChan for SharedChan { fn send(&self, x: T) { unsafe { let mut xx = Some(x); @@ -248,7 +248,7 @@ impl GenericChan for SharedChan { } } -impl GenericSmartChan for SharedChan { +impl GenericSmartChan for SharedChan { fn try_send(&self, x: T) -> bool { unsafe { let mut xx = Some(x); @@ -260,7 +260,7 @@ impl GenericSmartChan for SharedChan { } } -impl ::clone::Clone for SharedChan { +impl ::clone::Clone for SharedChan { fn clone(&self) -> SharedChan { SharedChan { ch: self.ch.clone() } } @@ -274,7 +274,7 @@ pub struct ChanOne { inner: Either, rtcomm::ChanOne> } -pub fn oneshot() -> (PortOne, ChanOne) { +pub fn oneshot() -> (PortOne, ChanOne) { let (port, chan) = match rt::context() { rt::OldTaskContext => match pipesy::oneshot() { (p, c) => (Left(p), Left(c)), @@ -288,7 +288,7 @@ pub fn oneshot() -> (PortOne, ChanOne) { return (port, chan); } -impl PortOne { +impl PortOne { pub fn recv(self) -> T { let PortOne { inner } = self; match inner { @@ -306,7 +306,7 @@ impl PortOne { } } -impl ChanOne { +impl ChanOne { pub fn send(self, data: T) { let ChanOne { inner } = self; match inner { @@ -324,7 +324,7 @@ impl ChanOne { } } -pub fn recv_one(port: PortOne) -> T { +pub fn recv_one(port: PortOne) -> T { let PortOne { inner } = port; match inner { Left(p) => pipesy::recv_one(p), @@ -332,7 +332,7 @@ pub fn recv_one(port: PortOne) -> T { } } -pub fn try_recv_one(port: PortOne) -> Option { +pub fn try_recv_one(port: PortOne) -> Option { let PortOne { inner } = port; match inner { Left(p) => pipesy::try_recv_one(p), @@ -340,7 +340,7 @@ pub fn try_recv_one(port: PortOne) -> Option { } } -pub fn send_one(chan: ChanOne, data: T) { +pub fn send_one(chan: ChanOne, data: T) { let ChanOne { inner } = chan; match inner { Left(c) => pipesy::send_one(c, data), @@ -348,7 +348,7 @@ pub fn send_one(chan: ChanOne, data: T) { } } -pub fn try_send_one(chan: ChanOne, data: T) -> bool { +pub fn try_send_one(chan: ChanOne, data: T) -> bool { let ChanOne { inner } = chan; match inner { Left(c) => pipesy::try_send_one(c, data), @@ -358,7 +358,7 @@ pub fn try_send_one(chan: ChanOne, data: T) -> bool { mod pipesy { - use kinds::Owned; + use kinds::Send; use option::{Option, Some, None}; use pipes::{recv, try_recv, peek, PacketHeader}; use super::{GenericChan, GenericSmartChan, GenericPort, Peekable, Selectable}; @@ -366,17 +366,17 @@ mod pipesy { use util::replace; /*proto! oneshot ( - Oneshot:send { + Oneshot:send { send(T) -> ! } )*/ #[allow(non_camel_case_types)] pub mod oneshot { - priv use core::kinds::Owned; + priv use core::kinds::Send; use ptr::to_mut_unsafe_ptr; - pub fn init() -> (server::Oneshot, client::Oneshot) { + pub fn init() -> (server::Oneshot, client::Oneshot) { pub use core::pipes::HasBuffer; let buffer = ~::core::pipes::Buffer { @@ -400,10 +400,10 @@ mod pipesy { #[allow(non_camel_case_types)] pub mod client { - priv use core::kinds::Owned; + priv use core::kinds::Send; #[allow(non_camel_case_types)] - pub fn try_send(pipe: Oneshot, x_0: T) -> + pub fn try_send(pipe: Oneshot, x_0: T) -> ::core::option::Option<()> { { use super::send; @@ -415,7 +415,7 @@ mod pipesy { } #[allow(non_camel_case_types)] - pub fn send(pipe: Oneshot, x_0: T) { + pub fn send(pipe: Oneshot, x_0: T) { { use super::send; let message = send(x_0); @@ -465,12 +465,12 @@ mod pipesy { } /// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair. - pub fn oneshot() -> (PortOne, ChanOne) { + pub fn oneshot() -> (PortOne, ChanOne) { let (port, chan) = oneshot::init(); (PortOne::new(port), ChanOne::new(chan)) } - impl PortOne { + impl PortOne { pub fn recv(self) -> T { recv_one(self) } pub fn try_recv(self) -> Option { try_recv_one(self) } pub fn unwrap(self) -> oneshot::server::Oneshot { @@ -480,7 +480,7 @@ mod pipesy { } } - impl ChanOne { + impl ChanOne { pub fn send(self, data: T) { send_one(self, data) } pub fn try_send(self, data: T) -> bool { try_send_one(self, data) } pub fn unwrap(self) -> oneshot::client::Oneshot { @@ -494,7 +494,7 @@ mod pipesy { * Receive a message from a oneshot pipe, failing if the connection was * closed. */ - pub fn recv_one(port: PortOne) -> T { + pub fn recv_one(port: PortOne) -> T { match port { PortOne { contents: port } => { let oneshot::send(message) = recv(port); @@ -504,7 +504,7 @@ mod pipesy { } /// Receive a message from a oneshot pipe unless the connection was closed. - pub fn try_recv_one (port: PortOne) -> Option { + pub fn try_recv_one (port: PortOne) -> Option { match port { PortOne { contents: port } => { let message = try_recv(port); @@ -520,7 +520,7 @@ mod pipesy { } /// Send a message on a oneshot pipe, failing if the connection was closed. - pub fn send_one(chan: ChanOne, data: T) { + pub fn send_one(chan: ChanOne, data: T) { match chan { ChanOne { contents: chan } => oneshot::client::send(chan, data), } @@ -530,7 +530,7 @@ mod pipesy { * Send a message on a oneshot pipe, or return false if the connection was * closed. */ - pub fn try_send_one(chan: ChanOne, data: T) -> bool { + pub fn try_send_one(chan: ChanOne, data: T) -> bool { match chan { ChanOne { contents: chan } => { oneshot::client::try_send(chan, data).is_some() @@ -541,16 +541,16 @@ mod pipesy { // Streams - Make pipes a little easier in general. /*proto! streamp ( - Open:send { + Open:send { data(T) -> Open } )*/ #[allow(non_camel_case_types)] pub mod streamp { - priv use core::kinds::Owned; + priv use core::kinds::Send; - pub fn init() -> (server::Open, client::Open) { + pub fn init() -> (server::Open, client::Open) { pub use core::pipes::HasBuffer; ::core::pipes::entangle() } @@ -560,10 +560,10 @@ mod pipesy { #[allow(non_camel_case_types)] pub mod client { - priv use core::kinds::Owned; + priv use core::kinds::Send; #[allow(non_camel_case_types)] - pub fn try_data(pipe: Open, x_0: T) -> + pub fn try_data(pipe: Open, x_0: T) -> ::core::option::Option> { { use super::data; @@ -576,7 +576,7 @@ mod pipesy { } #[allow(non_camel_case_types)] - pub fn data(pipe: Open, x_0: T) -> Open { + pub fn data(pipe: Open, x_0: T) -> Open { { use super::data; let (s, c) = ::core::pipes::entangle(); @@ -614,7 +614,7 @@ mod pipesy { These allow sending or receiving an unlimited number of messages. */ - pub fn stream() -> (Port, Chan) { + pub fn stream() -> (Port, Chan) { let (s, c) = streamp::init(); (Port { @@ -624,7 +624,7 @@ mod pipesy { }) } - impl GenericChan for Chan { + impl GenericChan for Chan { #[inline(always)] fn send(&self, x: T) { unsafe { @@ -635,7 +635,7 @@ mod pipesy { } } - impl GenericSmartChan for Chan { + impl GenericSmartChan for Chan { #[inline(always)] fn try_send(&self, x: T) -> bool { unsafe { @@ -652,7 +652,7 @@ mod pipesy { } } - impl GenericPort for Port { + impl GenericPort for Port { #[inline(always)] fn recv(&self) -> T { unsafe { @@ -680,7 +680,7 @@ mod pipesy { } } - impl Peekable for Port { + impl Peekable for Port { #[inline(always)] fn peek(&self) -> bool { unsafe { @@ -696,7 +696,7 @@ mod pipesy { } } - impl Selectable for Port { + impl Selectable for Port { fn header(&mut self) -> *mut PacketHeader { match self.endp { Some(ref mut endp) => endp.header(), @@ -724,15 +724,15 @@ pub fn select2i(a: &mut A, b: &mut B) } /// Receive a message from one of two endpoints. -pub trait Select2 { +pub trait Select2 { /// Receive a message or return `None` if a connection closes. fn try_select(&mut self) -> Either, Option>; /// Receive a message or fail if a connection closes. fn select(&mut self) -> Either; } -impl, Right:Selectable + GenericPort> Select2 diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index 9d5348ff98f0a..f350e10616805 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -24,7 +24,7 @@ The 4 kinds are scalar types and managed pointers, and exludes owned pointers. It also excludes types that implement `Drop`. -* Owned - owned types and types containing owned types. These types +* Send - owned types and types containing owned types. These types may be transferred across task boundaries. * Freeze - types that are deeply immutable. @@ -45,13 +45,13 @@ pub trait Copy { #[cfg(stage0)] #[lang="owned"] -pub trait Owned { +pub trait Send { // empty. } #[cfg(not(stage0))] #[lang="send"] -pub trait Owned { +pub trait Send { // empty. } diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs index 012ad0ed80d26..1d2dd086df8c2 100644 --- a/src/libstd/pipes.rs +++ b/src/libstd/pipes.rs @@ -88,7 +88,7 @@ use container::Container; use cast::{forget, transmute, transmute_copy}; use either::{Either, Left, Right}; use iterator::IteratorUtil; -use kinds::Owned; +use kinds::Send; use libc; use ops::Drop; use option::{None, Option, Some}; @@ -181,7 +181,7 @@ impl PacketHeader { transmute_copy(&self.buffer) } - pub fn set_buffer(&mut self, b: ~Buffer) { + pub fn set_buffer(&mut self, b: ~Buffer) { unsafe { self.buffer = transmute_copy(&b); } @@ -197,13 +197,13 @@ pub trait HasBuffer { fn set_buffer(&mut self, b: *libc::c_void); } -impl HasBuffer for Packet { +impl HasBuffer for Packet { fn set_buffer(&mut self, b: *libc::c_void) { self.header.buffer = b; } } -pub fn mk_packet() -> Packet { +pub fn mk_packet() -> Packet { Packet { header: PacketHeader(), payload: None, @@ -234,7 +234,7 @@ pub fn packet() -> *mut Packet { p } -pub fn entangle_buffer( +pub fn entangle_buffer( mut buffer: ~Buffer, init: &fn(*libc::c_void, x: &mut T) -> *mut Packet) -> (RecvPacketBuffered, SendPacketBuffered) { @@ -398,7 +398,7 @@ pub fn send(mut p: SendPacketBuffered, Fails if the sender closes the connection. */ -pub fn recv( +pub fn recv( p: RecvPacketBuffered) -> T { try_recv(p).expect("connection closed") } @@ -409,7 +409,7 @@ Returns `None` if the sender has closed the connection without sending a message, or `Some(T)` if a message was received. */ -pub fn try_recv(mut p: RecvPacketBuffered) +pub fn try_recv(mut p: RecvPacketBuffered) -> Option { let p_ = p.unwrap(); let p = unsafe { &mut *p_ }; @@ -429,7 +429,7 @@ pub fn try_recv(mut p: RecvPacketBuffered) } } -fn try_recv_(p: &mut Packet) -> Option { +fn try_recv_(p: &mut Packet) -> Option { // optimistic path match p.header.state { Full => { @@ -513,7 +513,7 @@ fn try_recv_(p: &mut Packet) -> Option { } /// Returns true if messages are available. -pub fn peek(p: &mut RecvPacketBuffered) -> bool { +pub fn peek(p: &mut RecvPacketBuffered) -> bool { unsafe { match (*p.header()).state { Empty | Terminated => false, @@ -523,7 +523,7 @@ pub fn peek(p: &mut RecvPacketBuffered) -> bool { } } -fn sender_terminate(p: *mut Packet) { +fn sender_terminate(p: *mut Packet) { let p = unsafe { &mut *p }; @@ -555,7 +555,7 @@ fn sender_terminate(p: *mut Packet) { } } -fn receiver_terminate(p: *mut Packet) { +fn receiver_terminate(p: *mut Packet) { let p = unsafe { &mut *p }; @@ -673,7 +673,7 @@ pub struct SendPacketBuffered { } #[unsafe_destructor] -impl Drop for SendPacketBuffered { +impl Drop for SendPacketBuffered { fn finalize(&self) { unsafe { let this: &mut SendPacketBuffered = transmute(self); @@ -731,7 +731,7 @@ pub struct RecvPacketBuffered { } #[unsafe_destructor] -impl Drop for RecvPacketBuffered { +impl Drop for RecvPacketBuffered { fn finalize(&self) { unsafe { let this: &mut RecvPacketBuffered = transmute(self); @@ -743,7 +743,7 @@ impl Drop for RecvPacketBuffered { } } -impl RecvPacketBuffered { +impl RecvPacketBuffered { pub fn unwrap(&mut self) -> *mut Packet { replace(&mut self.p, None).unwrap() } @@ -753,7 +753,7 @@ impl RecvPacketBuffered { } } -impl Selectable for RecvPacketBuffered { +impl Selectable for RecvPacketBuffered { fn header(&mut self) -> *mut PacketHeader { match self.p { Some(packet) => unsafe { @@ -809,7 +809,7 @@ Sometimes messages will be available on both endpoints at once. In this case, `select2` may return either `left` or `right`. */ -pub fn select2( +pub fn select2( mut a: RecvPacketBuffered, mut b: RecvPacketBuffered) -> Either<(Option, RecvPacketBuffered), @@ -849,7 +849,7 @@ pub fn select2i(a: &mut A, b: &mut B) /// Waits on a set of endpoints. Returns a message, its index, and a /// list of the remaining endpoints. -pub fn select(mut endpoints: ~[RecvPacketBuffered]) +pub fn select(mut endpoints: ~[RecvPacketBuffered]) -> (uint, Option, ~[RecvPacketBuffered]) { diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index eb16f5d776cd9..07df09c12b3d0 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -30,7 +30,7 @@ Rust's prelude has three main parts: // Reexported core operators pub use either::{Either, Left, Right}; pub use kinds::{Copy, Sized}; -pub use kinds::{Freeze, Owned}; +pub use kinds::{Freeze, Send}; pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Drop}; diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 8a8f31bbdfa52..03bc2da14138b 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -19,7 +19,7 @@ use option::*; use cast; use util; use ops::Drop; -use kinds::Owned; +use kinds::Send; use rt::sched::{Scheduler, Coroutine}; use rt::local::Local; use unstable::intrinsics::{atomic_xchg, atomic_load}; @@ -68,7 +68,7 @@ pub struct PortOneHack { suppress_finalize: bool } -pub fn oneshot() -> (PortOne, ChanOne) { +pub fn oneshot() -> (PortOne, ChanOne) { let packet: ~Packet = ~Packet { state: STATE_BOTH, payload: None @@ -307,20 +307,20 @@ pub struct Port { next: Cell>> } -pub fn stream() -> (Port, Chan) { +pub fn stream() -> (Port, Chan) { let (pone, cone) = oneshot(); let port = Port { next: Cell::new(pone) }; let chan = Chan { next: Cell::new(cone) }; return (port, chan); } -impl GenericChan for Chan { +impl GenericChan for Chan { fn send(&self, val: T) { self.try_send(val); } } -impl GenericSmartChan for Chan { +impl GenericSmartChan for Chan { fn try_send(&self, val: T) -> bool { let (next_pone, next_cone) = oneshot(); let cone = self.next.take(); diff --git a/src/libstd/rt/message_queue.rs b/src/libstd/rt/message_queue.rs index 5b60543344de1..d561e81d03271 100644 --- a/src/libstd/rt/message_queue.rs +++ b/src/libstd/rt/message_queue.rs @@ -9,7 +9,7 @@ // except according to those terms. use container::Container; -use kinds::Owned; +use kinds::Send; use vec::OwnedVector; use cell::Cell; use option::*; @@ -21,7 +21,7 @@ pub struct MessageQueue { priv queue: ~Exclusive<~[T]> } -impl MessageQueue { +impl MessageQueue { pub fn new() -> MessageQueue { MessageQueue { queue: ~exclusive(~[]) diff --git a/src/libstd/rt/work_queue.rs b/src/libstd/rt/work_queue.rs index cfffc55a58c80..00d2774426884 100644 --- a/src/libstd/rt/work_queue.rs +++ b/src/libstd/rt/work_queue.rs @@ -13,7 +13,7 @@ use option::*; use vec::OwnedVector; use unstable::sync::{Exclusive, exclusive}; use cell::Cell; -use kinds::Owned; +use kinds::Send; use clone::Clone; pub struct WorkQueue { @@ -21,7 +21,7 @@ pub struct WorkQueue { priv queue: ~Exclusive<~[T]> } -impl WorkQueue { +impl WorkQueue { pub fn new() -> WorkQueue { WorkQueue { queue: ~exclusive(~[]) diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index 223afbce091b8..435e1fc8e6245 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -353,7 +353,7 @@ impl TaskBuilder { } /// Runs a task, while transfering ownership of one argument to the child. - pub fn spawn_with(&mut self, arg: A, f: ~fn(v: A)) { + pub fn spawn_with(&mut self, arg: A, f: ~fn(v: A)) { let arg = Cell::new(arg); do self.spawn { f(arg.take()); @@ -373,7 +373,7 @@ impl TaskBuilder { * # Failure * Fails if a future_result was already set for this task. */ - pub fn try(&mut self, f: ~fn() -> T) -> Result { + pub fn try(&mut self, f: ~fn() -> T) -> Result { let (po, ch) = stream::(); let mut result = None; @@ -445,7 +445,7 @@ pub fn spawn_supervised(f: ~fn()) { task.spawn(f) } -pub fn spawn_with(arg: A, f: ~fn(v: A)) { +pub fn spawn_with(arg: A, f: ~fn(v: A)) { /*! * Runs a task, while transfering ownership of one argument to the * child. @@ -478,7 +478,7 @@ pub fn spawn_sched(mode: SchedMode, f: ~fn()) { task.spawn(f) } -pub fn try(f: ~fn() -> T) -> Result { +pub fn try(f: ~fn() -> T) -> Result { /*! * Execute a function in another task and return either the return value * of the function or result::err. diff --git a/src/libstd/unstable/global.rs b/src/libstd/unstable/global.rs index 96549a83a8cf3..d26720348c63a 100644 --- a/src/libstd/unstable/global.rs +++ b/src/libstd/unstable/global.rs @@ -27,7 +27,7 @@ avoid hitting the mutex. use cast::{transmute}; use clone::Clone; -use kinds::Owned; +use kinds::Send; use libc::{c_void}; use option::{Option, Some, None}; use ops::Drop; @@ -43,7 +43,7 @@ use sys::Closure; pub type GlobalDataKey<'self,T> = &'self fn(v: T); -pub unsafe fn global_data_clone_create( +pub unsafe fn global_data_clone_create( key: GlobalDataKey, create: &fn() -> ~T) -> T { /*! * Clone a global value or, if it has not been created, @@ -59,7 +59,7 @@ pub unsafe fn global_data_clone_create( global_data_clone_create_(key_ptr(key), create) } -unsafe fn global_data_clone_create_( +unsafe fn global_data_clone_create_( key: uint, create: &fn() -> ~T) -> T { let mut clone_value: Option = None; @@ -79,13 +79,13 @@ unsafe fn global_data_clone_create_( return clone_value.unwrap(); } -unsafe fn global_data_modify( +unsafe fn global_data_modify( key: GlobalDataKey, op: &fn(Option<~T>) -> Option<~T>) { global_data_modify_(key_ptr(key), op) } -unsafe fn global_data_modify_( +unsafe fn global_data_modify_( key: uint, op: &fn(Option<~T>) -> Option<~T>) { let mut old_dtor = None; @@ -124,7 +124,7 @@ unsafe fn global_data_modify_( } } -pub unsafe fn global_data_clone( +pub unsafe fn global_data_clone( key: GlobalDataKey) -> Option { let mut maybe_clone: Option = None; do global_data_modify(key) |current| { @@ -220,7 +220,7 @@ fn get_global_state() -> Exclusive { } } -fn key_ptr(key: GlobalDataKey) -> uint { +fn key_ptr(key: GlobalDataKey) -> uint { unsafe { let closure: Closure = transmute(key); return transmute(closure.code); diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index f0b178c667013..b8e987a481e64 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -17,7 +17,7 @@ use unstable::finally::Finally; use unstable::intrinsics; use ops::Drop; use clone::Clone; -use kinds::Owned; +use kinds::Send; /// An atomically reference counted pointer. /// @@ -31,7 +31,7 @@ struct AtomicRcBoxData { data: Option, } -impl UnsafeAtomicRcBox { +impl UnsafeAtomicRcBox { pub fn new(data: T) -> UnsafeAtomicRcBox { unsafe { let data = ~AtomicRcBoxData { count: 1, data: Some(data) }; @@ -61,7 +61,7 @@ impl UnsafeAtomicRcBox { } } -impl Clone for UnsafeAtomicRcBox { +impl Clone for UnsafeAtomicRcBox { fn clone(&self) -> UnsafeAtomicRcBox { unsafe { let mut data: ~AtomicRcBoxData = cast::transmute(self.data); @@ -144,7 +144,7 @@ pub struct Exclusive { x: UnsafeAtomicRcBox> } -pub fn exclusive(user_data: T) -> Exclusive { +pub fn exclusive(user_data: T) -> Exclusive { let data = ExData { lock: LittleLock(), failed: false, @@ -155,14 +155,14 @@ pub fn exclusive(user_data: T) -> Exclusive { } } -impl Clone for Exclusive { +impl Clone for Exclusive { // Duplicate an exclusive ARC, as std::arc::clone. fn clone(&self) -> Exclusive { Exclusive { x: self.x.clone() } } } -impl Exclusive { +impl Exclusive { // Exactly like std::arc::mutex_arc,access(), but with the little_lock // instead of a proper mutex. Same reason for being unsafe. // diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index aec9d2bd5b534..7b7e9a3852db3 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -149,7 +149,7 @@ pub static crate_node_id: node_id = 0; // The AST represents all type param bounds as types. // typeck::collect::compute_bounds matches these against // the "special" built-in traits (see middle::lang_items) and -// detects Copy, Send, Owned, and Freeze. +// detects Copy, Send, Send, and Freeze. pub enum TyParamBound { TraitTyParamBound(@trait_ref), RegionTyParamBound diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs index 41be3a775c164..57af3422ce2bb 100644 --- a/src/libsyntax/ext/deriving/to_str.rs +++ b/src/libsyntax/ext/deriving/to_str.rs @@ -31,7 +31,7 @@ pub fn expand_deriving_to_str(cx: @ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[], - ret_ty: Ptr(~Literal(Path::new_local("str")), Owned), + ret_ty: Ptr(~Literal(Path::new_local("str")), Send), const_nonmatching: false, combine_substructure: to_str_substructure } diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs index 3b39cb691a629..347683f0b21da 100644 --- a/src/libsyntax/ext/deriving/ty.rs +++ b/src/libsyntax/ext/deriving/ty.rs @@ -24,7 +24,7 @@ use opt_vec; /// The types of pointers pub enum PtrTy<'self> { - Owned, // ~ + Send, // ~ Managed(ast::mutability), // @[mut] Borrowed(Option<&'self str>, ast::mutability), // &['lifetime] [mut] } @@ -130,7 +130,7 @@ impl<'self> Ty<'self> { Ptr(ref ty, ref ptr) => { let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); match *ptr { - Owned => { + Send => { cx.ty_uniq(span, raw_ty) } Managed(mutbl) => { @@ -249,7 +249,7 @@ pub fn get_explicit_self(cx: @ExtCtxt, span: span, self_ptr: &Option) let self_ty = respan( span, match *ptr { - Owned => ast::sty_uniq(ast::m_imm), + Send => ast::sty_uniq(ast::m_imm), Managed(mutbl) => ast::sty_box(mutbl), Borrowed(ref lt, mutbl) => { let lt = lt.map(|s| @cx.lifetime(span, diff --git a/src/test/auxiliary/cci_capture_clause.rs b/src/test/auxiliary/cci_capture_clause.rs index e58b28aa3ded1..98c364590be83 100644 --- a/src/test/auxiliary/cci_capture_clause.rs +++ b/src/test/auxiliary/cci_capture_clause.rs @@ -11,7 +11,7 @@ use std::comm::*; use std::task; -pub fn foo(x: T) -> Port { +pub fn foo(x: T) -> Port { let (p, c) = stream(); do task::spawn() { c.send(x); diff --git a/src/test/bench/pingpong.rs b/src/test/bench/pingpong.rs index 63e4174a0fc7c..1d32a78303a8f 100644 --- a/src/test/bench/pingpong.rs +++ b/src/test/bench/pingpong.rs @@ -82,7 +82,7 @@ endpoint. The send endpoint is returned to the caller and the receive endpoint is passed to the new task. */ -pub fn spawn_service( +pub fn spawn_service( init: extern fn() -> (RecvPacketBuffered, SendPacketBuffered), service: ~fn(v: RecvPacketBuffered)) @@ -103,7 +103,7 @@ pub fn spawn_service( receive state. */ -pub fn spawn_service_recv( +pub fn spawn_service_recv( init: extern fn() -> (SendPacketBuffered, RecvPacketBuffered), service: ~fn(v: SendPacketBuffered)) @@ -120,7 +120,7 @@ pub fn spawn_service_recv( client } -fn switch(endp: std::pipes::RecvPacketBuffered, +fn switch(endp: std::pipes::RecvPacketBuffered, f: &fn(v: Option) -> U) -> U { f(std::pipes::try_recv(endp)) diff --git a/src/test/compile-fail/closure-bounds-subtype.rs b/src/test/compile-fail/closure-bounds-subtype.rs index ebec113cedc53..9b3a58d010ed2 100644 --- a/src/test/compile-fail/closure-bounds-subtype.rs +++ b/src/test/compile-fail/closure-bounds-subtype.rs @@ -4,28 +4,28 @@ fn take_any(_: &fn()) { fn take_copyable(_: &fn:Copy()) { } -fn take_copyable_owned(_: &fn:Copy+Owned()) { +fn take_copyable_owned(_: &fn:Copy+Send()) { } fn give_any(f: &fn()) { take_any(f); take_copyable(f); //~ ERROR expected bounds `Copy` but found no bounds - take_copyable_owned(f); //~ ERROR expected bounds `Copy+Owned` but found no bounds + take_copyable_owned(f); //~ ERROR expected bounds `Copy+Send` but found no bounds } fn give_copyable(f: &fn:Copy()) { take_any(f); take_copyable(f); - take_copyable_owned(f); //~ ERROR expected bounds `Copy+Owned` but found bounds `Copy` + take_copyable_owned(f); //~ ERROR expected bounds `Copy+Send` but found bounds `Copy` } -fn give_owned(f: &fn:Owned()) { +fn give_owned(f: &fn:Send()) { take_any(f); - take_copyable(f); //~ ERROR expected bounds `Copy` but found bounds `Owned` - take_copyable_owned(f); //~ ERROR expected bounds `Copy+Owned` but found bounds `Owned` + take_copyable(f); //~ ERROR expected bounds `Copy` but found bounds `Send` + take_copyable_owned(f); //~ ERROR expected bounds `Copy+Send` but found bounds `Send` } -fn give_copyable_owned(f: &fn:Copy+Owned()) { +fn give_copyable_owned(f: &fn:Copy+Send()) { take_any(f); take_copyable(f); take_copyable_owned(f); diff --git a/src/test/compile-fail/issue-2766-a.rs b/src/test/compile-fail/issue-2766-a.rs index 91ae0e1c07a55..c5d13c81b7c59 100644 --- a/src/test/compile-fail/issue-2766-a.rs +++ b/src/test/compile-fail/issue-2766-a.rs @@ -9,12 +9,12 @@ // except according to those terms. pub mod stream { - pub enum Stream { send(T, ::stream::server::Stream), } + pub enum Stream { send(T, ::stream::server::Stream), } pub mod server { use std::option; use std::pipes; - impl Stream { + impl Stream { pub fn recv() -> extern fn(v: Stream) -> ::stream::Stream { // resolve really should report just one error here. // Change the test case when it changes. @@ -28,7 +28,7 @@ pub mod stream { } } - pub type Stream = pipes::RecvPacket<::stream::Stream>; + pub type Stream = pipes::RecvPacket<::stream::Stream>; } } diff --git a/src/test/compile-fail/kindck-destructor-owned.rs b/src/test/compile-fail/kindck-destructor-owned.rs index faad36a15d2fa..4c957d6bce4c5 100644 --- a/src/test/compile-fail/kindck-destructor-owned.rs +++ b/src/test/compile-fail/kindck-destructor-owned.rs @@ -2,7 +2,7 @@ struct Foo { f: @mut int, } -impl Drop for Foo { //~ ERROR cannot implement a destructor on a struct that is not Owned +impl Drop for Foo { //~ ERROR cannot implement a destructor on a struct that is not Send fn finalize(&self) { *self.f = 10; } diff --git a/src/test/compile-fail/liveness-use-after-send.rs b/src/test/compile-fail/liveness-use-after-send.rs index 23d3fff01cf3c..72555d7e85119 100644 --- a/src/test/compile-fail/liveness-use-after-send.rs +++ b/src/test/compile-fail/liveness-use-after-send.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn send(ch: _chan, data: T) { +fn send(ch: _chan, data: T) { debug!(ch); debug!(data); fail!(); diff --git a/src/test/compile-fail/non_owned-enum.rs b/src/test/compile-fail/non_owned-enum.rs index 79c2be8183a62..6068b7f173030 100644 --- a/src/test/compile-fail/non_owned-enum.rs +++ b/src/test/compile-fail/non_owned-enum.rs @@ -11,9 +11,9 @@ #[non_owned] enum Foo { A } -fn bar(_: T) {} +fn bar(_: T) {} fn main() { let x = A; - bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Owned` + bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Send` } diff --git a/src/test/compile-fail/non_owned-struct.rs b/src/test/compile-fail/non_owned-struct.rs index 2d0bc9a7e8e46..b6f29df05752d 100644 --- a/src/test/compile-fail/non_owned-struct.rs +++ b/src/test/compile-fail/non_owned-struct.rs @@ -11,9 +11,9 @@ #[non_owned] struct Foo { a: int } -fn bar(_: T) {} +fn bar(_: T) {} fn main() { let x = Foo { a: 5 }; - bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Owned` + bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Send` } diff --git a/src/test/compile-fail/unique-unique-kind.rs b/src/test/compile-fail/unique-unique-kind.rs index 26058bf89cad7..d51df4979e352 100644 --- a/src/test/compile-fail/unique-unique-kind.rs +++ b/src/test/compile-fail/unique-unique-kind.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(_i: T) { +fn f(_i: T) { } fn main() { let i = ~@100; - f(i); //~ ERROR does not fulfill `Owned` + f(i); //~ ERROR does not fulfill `Send` } diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs index 58de0926f7c66..de089dcf914b9 100644 --- a/src/test/compile-fail/unsendable-class.rs +++ b/src/test/compile-fail/unsendable-class.rs @@ -27,6 +27,6 @@ fn foo(i:int, j: @~str) -> foo { fn main() { let cat = ~"kitty"; - let (_, ch) = comm::stream(); //~ ERROR does not fulfill `Owned` - ch.send(foo(42, @(cat))); //~ ERROR does not fulfill `Owned` + let (_, ch) = comm::stream(); //~ ERROR does not fulfill `Send` + ch.send(foo(42, @(cat))); //~ ERROR does not fulfill `Send` } diff --git a/src/test/run-fail/bug-811.rs b/src/test/run-fail/bug-811.rs index b497b0224b9f7..992747187f635 100644 --- a/src/test/run-fail/bug-811.rs +++ b/src/test/run-fail/bug-811.rs @@ -19,6 +19,6 @@ struct chan_t { port: port_id, } -fn send(ch: chan_t, data: T) { fail!(); } +fn send(ch: chan_t, data: T) { fail!(); } fn main() { fail!("quux"); } diff --git a/src/test/run-pass/alignment-gep-tup-like-2.rs b/src/test/run-pass/alignment-gep-tup-like-2.rs index 6bf4e96bc053d..cfef97346a52d 100644 --- a/src/test/run-pass/alignment-gep-tup-like-2.rs +++ b/src/test/run-pass/alignment-gep-tup-like-2.rs @@ -23,7 +23,7 @@ fn make_cycle(a: A) { g.rec = Some(g); } -fn f(a: A, b: B) -> @fn() -> (A, B) { +fn f(a: A, b: B) -> @fn() -> (A, B) { let result: @fn() -> (A, B) = || (a, b); result } diff --git a/src/test/run-pass/fixed-point-bind-unique.rs b/src/test/run-pass/fixed-point-bind-unique.rs index 53f9c723a4738..c7b64fde3fd5a 100644 --- a/src/test/run-pass/fixed-point-bind-unique.rs +++ b/src/test/run-pass/fixed-point-bind-unique.rs @@ -10,11 +10,11 @@ // xfail-fast -fn fix_help(f: extern fn(@fn(A) -> B, A) -> B, x: A) -> B { +fn fix_help(f: extern fn(@fn(A) -> B, A) -> B, x: A) -> B { return f(|a| fix_help(f, a), x); } -fn fix(f: extern fn(@fn(A) -> B, A) -> B) -> @fn(A) -> B { +fn fix(f: extern fn(@fn(A) -> B, A) -> B) -> @fn(A) -> B { return |a| fix_help(f, a); } diff --git a/src/test/run-pass/fn-bare-spawn.rs b/src/test/run-pass/fn-bare-spawn.rs index 4f0f451a08c09..e9954be93575c 100644 --- a/src/test/run-pass/fn-bare-spawn.rs +++ b/src/test/run-pass/fn-bare-spawn.rs @@ -10,7 +10,7 @@ // This is what the signature to spawn should look like with bare functions -fn spawn(val: T, f: extern fn(T)) { +fn spawn(val: T, f: extern fn(T)) { f(val); } diff --git a/src/test/run-pass/generic-alias-unique.rs b/src/test/run-pass/generic-alias-unique.rs index ad271186639bd..815cc1bc79bcd 100644 --- a/src/test/run-pass/generic-alias-unique.rs +++ b/src/test/run-pass/generic-alias-unique.rs @@ -10,7 +10,7 @@ -fn id(t: T) -> T { return t; } +fn id(t: T) -> T { return t; } pub fn main() { let expected = ~100; diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index 4ef83e405be40..b01216ff8feb7 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -39,7 +39,7 @@ pub mod pipes { payload: Option } - pub fn packet() -> *packet { + pub fn packet() -> *packet { unsafe { let p: *packet = cast::transmute(~Stuff{ state: empty, @@ -74,7 +74,7 @@ pub mod pipes { } } - pub fn send(mut p: send_packet, payload: T) { + pub fn send(mut p: send_packet, payload: T) { let mut p = p.unwrap(); let mut p = unsafe { uniquify(p) }; assert!((*p).payload.is_none()); @@ -100,7 +100,7 @@ pub mod pipes { } } - pub fn recv(mut p: recv_packet) -> Option { + pub fn recv(mut p: recv_packet) -> Option { let mut p = p.unwrap(); let mut p = unsafe { uniquify(p) }; loop { @@ -120,7 +120,7 @@ pub mod pipes { } } - pub fn sender_terminate(mut p: *packet) { + pub fn sender_terminate(mut p: *packet) { let mut p = unsafe { uniquify(p) }; match swap_state_rel(&mut (*p).state, terminated) { empty | blocked => { @@ -137,7 +137,7 @@ pub mod pipes { } } - pub fn receiver_terminate(mut p: *packet) { + pub fn receiver_terminate(mut p: *packet) { let mut p = unsafe { uniquify(p) }; match swap_state_rel(&mut (*p).state, terminated) { empty => { @@ -159,7 +159,7 @@ pub mod pipes { } #[unsafe_destructor] - impl Drop for send_packet { + impl Drop for send_packet { fn finalize(&self) { unsafe { if self.p != None { @@ -172,13 +172,13 @@ pub mod pipes { } } - impl send_packet { + impl send_packet { pub fn unwrap(&mut self) -> *packet { util::replace(&mut self.p, None).unwrap() } } - pub fn send_packet(p: *packet) -> send_packet { + pub fn send_packet(p: *packet) -> send_packet { send_packet { p: Some(p) } @@ -189,7 +189,7 @@ pub mod pipes { } #[unsafe_destructor] - impl Drop for recv_packet { + impl Drop for recv_packet { fn finalize(&self) { unsafe { if self.p != None { @@ -202,19 +202,19 @@ pub mod pipes { } } - impl recv_packet { + impl recv_packet { pub fn unwrap(&mut self) -> *packet { util::replace(&mut self.p, None).unwrap() } } - pub fn recv_packet(p: *packet) -> recv_packet { + pub fn recv_packet(p: *packet) -> recv_packet { recv_packet { p: Some(p) } } - pub fn entangle() -> (send_packet, recv_packet) { + pub fn entangle() -> (send_packet, recv_packet) { let p = packet(); (send_packet(p), recv_packet(p)) } diff --git a/src/test/run-pass/issue-2834.rs b/src/test/run-pass/issue-2834.rs index 5d3a2d2331c90..b0ddccf28944b 100644 --- a/src/test/run-pass/issue-2834.rs +++ b/src/test/run-pass/issue-2834.rs @@ -12,7 +12,7 @@ // proto! streamp ( - open:send { + open:send { data(T) -> open } ) diff --git a/src/test/run-pass/issue-2930.rs b/src/test/run-pass/issue-2930.rs index cfce19826d7e0..10a19d62bd97b 100644 --- a/src/test/run-pass/issue-2930.rs +++ b/src/test/run-pass/issue-2930.rs @@ -9,7 +9,7 @@ // except according to those terms. proto! stream ( - Stream:send { + Stream:send { send(T) -> Stream } ) diff --git a/src/test/run-pass/pipe-bank-proto.rs b/src/test/run-pass/pipe-bank-proto.rs index d723fa3220945..47ab69e0b36ae 100644 --- a/src/test/run-pass/pipe-bank-proto.rs +++ b/src/test/run-pass/pipe-bank-proto.rs @@ -49,7 +49,7 @@ macro_rules! move_it ( { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } } ) -fn switch(endp: pipes::RecvPacket, +fn switch(endp: pipes::RecvPacket, f: &fn(v: Option) -> U) -> U { f(pipes::try_recv(endp)) } diff --git a/src/test/run-pass/pipe-select.rs b/src/test/run-pass/pipe-select.rs index 0a860d0a1e22c..36f144152f2a3 100644 --- a/src/test/run-pass/pipe-select.rs +++ b/src/test/run-pass/pipe-select.rs @@ -29,12 +29,12 @@ proto! oneshot ( ) proto! stream ( - Stream:send { + Stream:send { send(T) -> Stream } ) -pub fn spawn_service( +pub fn spawn_service( init: extern fn() -> (RecvPacketBuffered, SendPacketBuffered), service: ~fn(v: RecvPacketBuffered)) diff --git a/src/test/run-pass/pipe-sleep.rs b/src/test/run-pass/pipe-sleep.rs index dc88f36ba113a..dbf860cd04075 100644 --- a/src/test/run-pass/pipe-sleep.rs +++ b/src/test/run-pass/pipe-sleep.rs @@ -33,7 +33,7 @@ endpoint. The send endpoint is returned to the caller and the receive endpoint is passed to the new task. */ -pub fn spawn_service( +pub fn spawn_service( init: extern fn() -> (RecvPacketBuffered, SendPacketBuffered), service: ~fn(v: RecvPacketBuffered)) diff --git a/src/test/run-pass/send-type-inference.rs b/src/test/run-pass/send-type-inference.rs index bdb1fbaf42261..4fcbc789f57b2 100644 --- a/src/test/run-pass/send-type-inference.rs +++ b/src/test/run-pass/send-type-inference.rs @@ -16,7 +16,7 @@ struct Command { val: V } -fn cache_server(c: Chan>>) { +fn cache_server(c: Chan>>) { let (ctrl_port, ctrl_chan) = stream(); c.send(ctrl_chan); } diff --git a/src/test/run-pass/type-param-constraints.rs b/src/test/run-pass/type-param-constraints.rs index bd6165806c273..fd721e00f2558 100644 --- a/src/test/run-pass/type-param-constraints.rs +++ b/src/test/run-pass/type-param-constraints.rs @@ -12,7 +12,7 @@ fn p_foo(pinned: T) { } fn s_foo(shared: T) { } -fn u_foo(unique: T) { } +fn u_foo(unique: T) { } struct r { i: int, diff --git a/src/test/run-pass/uniq-cc-generic.rs b/src/test/run-pass/uniq-cc-generic.rs index b54b3b52692ed..2c3424d1f06fd 100644 --- a/src/test/run-pass/uniq-cc-generic.rs +++ b/src/test/run-pass/uniq-cc-generic.rs @@ -20,7 +20,7 @@ struct Pointy { d : ~fn() -> uint, } -fn make_uniq_closure(a: A) -> ~fn() -> uint { +fn make_uniq_closure(a: A) -> ~fn() -> uint { let result: ~fn() -> uint = || ptr::to_unsafe_ptr(&a) as uint; result } diff --git a/src/test/run-pass/unique-kinds.rs b/src/test/run-pass/unique-kinds.rs index b3ce71dcbff5d..391881deff668 100644 --- a/src/test/run-pass/unique-kinds.rs +++ b/src/test/run-pass/unique-kinds.rs @@ -12,11 +12,11 @@ use std::cmp::Eq; fn sendable() { - fn f(i: T, j: T) { + fn f(i: T, j: T) { assert_eq!(i, j); } - fn g(i: T, j: T) { + fn g(i: T, j: T) { assert!(i != j); } From 5eeff469ea5be33b4a21577449098667683cbfcd Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 6 Jun 2013 18:54:14 -0700 Subject: [PATCH 05/13] librustc: Disallow "mut" from distributing over bindings. This is the backwards-incompatible part of per-binding-site "mut". --- doc/rust.md | 14 ++-- doc/tutorial-ffi.md | 4 +- src/libextra/md4.rs | 3 +- src/libextra/net_url.rs | 4 +- src/libextra/num/bigint.rs | 8 ++- src/libextra/timer.rs | 4 +- src/librustc/middle/trans/cabi_arm.rs | 4 +- src/librustc/middle/trans/cabi_mips.rs | 4 +- src/librustc/middle/trans/cabi_x86_64.rs | 4 +- src/librustc/middle/trans/callee.rs | 3 +- src/librustc/middle/trans/expr.rs | 5 +- src/libstd/io.rs | 7 +- src/libstd/num/int_macros.rs | 3 +- src/libstd/num/uint_macros.rs | 3 +- src/libstd/rand.rs | 3 +- src/libstd/rand/distributions.rs | 3 +- src/libstd/rt/io/extensions.rs | 7 +- src/libstd/str.rs | 70 ++++++++++++++++++- src/libstd/task/spawn.rs | 4 +- src/libstd/to_str.rs | 15 ++-- src/libstd/vec.rs | 9 ++- src/libsyntax/ast_util.rs | 9 +++ src/libsyntax/parse/obsolete.rs | 6 ++ src/libsyntax/parse/parser.rs | 16 ++++- src/test/bench/shootout-mandelbrot.rs | 5 +- .../compile-fail/kindck-destructor-owned.rs | 2 +- src/test/compile-fail/kindck-nonsendable-1.rs | 6 +- src/test/compile-fail/no-send-res-ports.rs | 2 +- src/test/compile-fail/non_owned-enum.rs | 2 +- src/test/compile-fail/non_owned-struct.rs | 2 +- src/test/run-pass/let-destruct-fresh-mem.rs | 4 +- src/test/run-pass/pipe-peek.rs | 4 +- 32 files changed, 190 insertions(+), 49 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 3c0828def154a..bce5b95a73756 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2859,13 +2859,13 @@ call to the method `make_string`. Types in Rust are categorized into kinds, based on various properties of the components of the type. The kinds are: -`Const` +`Freeze` : Types of this kind are deeply immutable; they contain no mutable memory locations directly or indirectly via pointers. -`Owned` +`Send` : Types of this kind can be safely sent between tasks. This kind includes scalars, owning pointers, owned closures, and - structural types containing only other owned types. All `Owned` types are `Static`. + structural types containing only other owned types. All `Send` types are `Static`. `Static` : Types of this kind do not contain any borrowed pointers; this can be a useful guarantee for code that breaks borrowing assumptions using [`unsafe` operations](#unsafe-functions). @@ -2879,7 +2879,7 @@ The kinds are: trait provides a single method `finalize` that takes no parameters, and is run when values of the type are dropped. Such a method is called a "destructor", and are always executed in "top-down" order: a value is completely destroyed - before any of the values it owns run their destructors. Only `Owned` types + before any of the values it owns run their destructors. Only `Send` types that do not implement `Copy` can implement `Drop`. > **Note:** The `finalize` method may be renamed in future versions of Rust. @@ -2965,10 +2965,10 @@ frame they are allocated within. A task owns all memory it can *safely* reach through local variables, as well as managed, owning and borrowed pointers. -When a task sends a value that has the `Owned` trait to another task, +When a task sends a value that has the `Send` trait to another task, it loses ownership of the value sent and can no longer refer to it. This is statically guaranteed by the combined use of "move semantics", -and the compiler-checked _meaning_ of the `Owned` trait: +and the compiler-checked _meaning_ of the `Send` trait: it is only instantiated for (transitively) sendable kinds of data constructor and pointers, never including managed or borrowed pointers. @@ -3113,7 +3113,7 @@ These include: - read-only and read-write shared variables with various safe mutual exclusion patterns - simple locks and semaphores -When such facilities carry values, the values are restricted to the [`Owned` type-kind](#type-kinds). +When such facilities carry values, the values are restricted to the [`Send` type-kind](#type-kinds). Restricting communication interfaces to this kind ensures that no borrowed or managed pointers move between tasks. Thus access to an entire data structure can be mediated through its owning "root" value; no further locking or copying is required to avoid data races within the substructure of such a value. diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md index d3c682ce1adcd..2319acaa68f5c 100644 --- a/doc/tutorial-ffi.md +++ b/doc/tutorial-ffi.md @@ -159,7 +159,7 @@ pub struct Unique { priv ptr: *mut T } -impl Unique { +impl Unique { pub fn new(value: T) -> Unique { unsafe { let ptr = malloc(std::sys::size_of::() as size_t) as *mut T; @@ -182,7 +182,7 @@ impl Unique { } #[unsafe_destructor] -impl Drop for Unique { +impl Drop for Unique { fn finalize(&self) { unsafe { let x = intrinsics::init(); // dummy value to swap in diff --git a/src/libextra/md4.rs b/src/libextra/md4.rs index 6c972a313c420..2534fedd9611f 100644 --- a/src/libextra/md4.rs +++ b/src/libextra/md4.rs @@ -59,7 +59,8 @@ pub fn md4(msg: &[u8]) -> Quad { while i < e { let (aa, bb, cc, dd) = (a, b, c, d); - let mut (j, base) = (0u, i); + let mut j = 0u; + let mut base = i; while j < 16u { x[j] = (msg[base] as u32) + (msg[base + 1u] as u32 << 8u32) + (msg[base + 2u] as u32 << 16u32) + diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index 31d728f18130b..30ec0967f278e 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -416,7 +416,9 @@ fn get_authority(rawurl: &str) -> let mut port = None; let mut colon_count = 0; - let mut (pos, begin, end) = (0, 2, len); + let mut pos = 0; + let mut begin = 2; + let mut end = len; for rawurl.iter().enumerate().advance |(i,c)| { if i < 2 { loop; } // ignore the leading // diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 4baa8877bda1e..93ffc4a7e876d 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -382,7 +382,10 @@ impl Integer for BigUint { let mut d = Zero::zero::(); let mut n = 1; while m >= b { - let mut (d0, d_unit, b_unit) = div_estimate(&m, &b, n); + let (d0, d_unit, b_unit) = div_estimate(&m, &b, n); + let mut d0 = d0; + let mut d_unit = d_unit; + let mut b_unit = b_unit; let mut prod = b * d0; while prod > m { // FIXME(#6050): overloaded operators force moves with generic types @@ -444,7 +447,8 @@ impl Integer for BigUint { fn gcd(&self, other: &BigUint) -> BigUint { // Use Euclid's algorithm - let mut (m, n) = (copy *self, copy *other); + let mut m = copy *self; + let mut n = copy *other; while !m.is_zero() { let temp = m; m = n % temp; diff --git a/src/libextra/timer.rs b/src/libextra/timer.rs index bf548c9e408e4..f2200789c3542 100644 --- a/src/libextra/timer.rs +++ b/src/libextra/timer.rs @@ -123,7 +123,9 @@ pub fn recv_timeout(iotask: &IoTask, msecs: uint, wait_po: &Port) -> Option { - let mut (timeout_po, timeout_ch) = stream::<()>(); + let (timeout_po, timeout_ch) = stream::<()>(); + let mut timeout_po = timeout_po; + let mut timeout_ch = timeout_ch; delayed_send(iotask, msecs, &timeout_ch, ()); // XXX: Workaround due to ports and channels not being &mut. They should diff --git a/src/librustc/middle/trans/cabi_arm.rs b/src/librustc/middle/trans/cabi_arm.rs index d59635ccd762f..b7fbfb58da3fc 100644 --- a/src/librustc/middle/trans/cabi_arm.rs +++ b/src/librustc/middle/trans/cabi_arm.rs @@ -145,12 +145,14 @@ impl ABIInfo for ARM_ABIInfo { attrs.push(attr); } - let mut (ret_ty, ret_attr) = if ret_def { + let (ret_ty, ret_attr) = if ret_def { classify_ret_ty(rty) } else { (LLVMType { cast: false, ty: T_void() }, None) }; + let mut ret_ty = ret_ty; + let sret = ret_attr.is_some(); if sret { arg_tys.unshift(ret_ty); diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index 6be398c0bb2b1..13841d3e5cdc1 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -195,12 +195,14 @@ impl ABIInfo for MIPS_ABIInfo { atys: &[TypeRef], rty: TypeRef, ret_def: bool) -> FnType { - let mut (ret_ty, ret_attr) = if ret_def { + let (ret_ty, ret_attr) = if ret_def { classify_ret_ty(rty) } else { (LLVMType { cast: false, ty: T_void() }, None) }; + let mut ret_ty = ret_ty; + let sret = ret_attr.is_some(); let mut arg_tys = ~[]; let mut attrs = ~[]; diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index eb2d7e619eb75..d34d08b66c815 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -373,8 +373,10 @@ fn x86_64_tys(atys: &[TypeRef], arg_tys.push(ty); attrs.push(attr); } - let mut (ret_ty, ret_attr) = x86_64_ty(rty, is_ret_bysret, + let (ret_ty, ret_attr) = x86_64_ty(rty, + is_ret_bysret, StructRetAttribute); + let mut ret_ty = ret_ty; let sret = ret_attr.is_some(); if sret { arg_tys = vec::append(~[ret_ty], arg_tys); diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 2ef751579202f..e2373a809e76c 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -343,9 +343,10 @@ pub fn trans_fn_ref_with_vtables( // Should be either intra-crate or inlined. assert_eq!(def_id.crate, ast::local_crate); - let mut (val, must_cast) = + let (val, must_cast) = monomorphize::monomorphic_fn(ccx, def_id, &substs, vtables, opt_impl_did, Some(ref_id)); + let mut val = val; if must_cast && ref_id != 0 { // Monotype of the REFERENCE to the function (type params // are subst'd) diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 13fc610e94a8d..4ac0746027d67 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -906,9 +906,12 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { let scaled_ix = Mul(bcx, ix_val, vt.llunit_size); base::maybe_name_value(bcx.ccx(), scaled_ix, "scaled_ix"); - let mut (bcx, base, len) = + let (bcx, base, len) = base_datum.get_vec_base_and_len(bcx, index_expr.span, index_expr.id, 0); + let mut bcx = bcx; + let mut base = base; + let mut len = len; if ty::type_is_str(base_ty) { // acccount for null terminator in the case of string diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 6f065d74fa2e6..f8b931cc76b23 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -771,7 +771,9 @@ impl ReaderUtil for T { fn read_le_uint_n(&self, nbytes: uint) -> u64 { assert!(nbytes > 0 && nbytes <= 8); - let mut (val, pos, i) = (0u64, 0, nbytes); + let mut val = 0u64; + let mut pos = 0; + let mut i = nbytes; while i > 0 { val += (self.read_u8() as u64) << pos; pos += 8; @@ -787,7 +789,8 @@ impl ReaderUtil for T { fn read_be_uint_n(&self, nbytes: uint) -> u64 { assert!(nbytes > 0 && nbytes <= 8); - let mut (val, i) = (0u64, nbytes); + let mut val = 0u64; + let mut i = nbytes; while i > 0 { i -= 1; val += (self.read_u8() as u64) << i * 8; diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 74f74d11b7302..fb38efded6113 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -400,7 +400,8 @@ impl Integer for $T { #[inline(always)] fn gcd(&self, other: &$T) -> $T { // Use Euclid's algorithm - let mut (m, n) = (*self, *other); + let mut m = *self; + let mut n = *other; while m != 0 { let temp = m; m = n % temp; diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 2bc1ca9c67330..b30d2fd7b6d1a 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -237,7 +237,8 @@ impl Integer for $T { #[inline(always)] fn gcd(&self, other: &$T) -> $T { // Use Euclid's algorithm - let mut (m, n) = (*self, *other); + let mut m = *self; + let mut n = *other; while m != 0 { let temp = m; m = n % temp; diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 7946f7e4f13f6..5b016134be5f0 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -720,7 +720,8 @@ impl IsaacRng { fn isaac(&mut self) { self.c += 1; // abbreviations - let mut (a, b) = (self.a, self.b + self.c); + let mut a = self.a; + let mut b = self.b + self.c; static midpoint: uint = RAND_SIZE as uint / 2; diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs index f08d967cbe022..5699cd1d5aa57 100644 --- a/src/libstd/rand/distributions.rs +++ b/src/libstd/rand/distributions.rs @@ -89,7 +89,8 @@ impl Rand for StandardNormal { // do-while, so the condition should be true on the first // run, they get overwritten anyway (0 < 1, so these are // good). - let mut (x, y) = (1.0, 0.0); + let mut x = 1.0; + let mut y = 0.0; // XXX infinities? while -2.0*y < x * x { diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index 727ab13a4f6f7..f313dde10b254 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -342,7 +342,9 @@ impl ReaderByteConversions for T { fn read_le_uint_n(&mut self, nbytes: uint) -> u64 { assert!(nbytes > 0 && nbytes <= 8); - let mut (val, pos, i) = (0u64, 0, nbytes); + let mut val = 0u64; + let mut pos = 0; + let mut i = nbytes; while i > 0 { val += (self.read_u8() as u64) << pos; pos += 8; @@ -358,7 +360,8 @@ impl ReaderByteConversions for T { fn read_be_uint_n(&mut self, nbytes: uint) -> u64 { assert!(nbytes > 0 && nbytes <= 8); - let mut (val, i) = (0u64, nbytes); + let mut val = 0u64; + let mut i = nbytes; while i > 0 { i -= 1; val += (self.read_u8() as u64) << i * 8; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 1086fcaa75cfc..2b91d04d8b056 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -522,6 +522,31 @@ pub fn each_split_within<'a>(ss: &'a str, return cont; } +/** + * Replace all occurrences of one string with another + * + * # Arguments + * + * * s - The string containing substrings to replace + * * from - The string to replace + * * to - The replacement string + * + * # Return value + * + * The original string with all occurances of `from` replaced with `to` + */ +pub fn replace(s: &str, from: &str, to: &str) -> ~str { + let mut result = ~""; + let mut last_end = 0; + for s.matches_index_iter(from).advance |(start, end)| { + result.push_str(unsafe{raw::slice_bytes(s, last_end, start)}); + result.push_str(to); + last_end = end; + } + result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())}); + result +} + /* Section: Comparing strings */ @@ -894,6 +919,48 @@ pub fn with_capacity(capacity: uint) -> ~str { buf } +/** + * As char_len but for a slice of a string + * + * # Arguments + * + * * s - A valid string + * * start - The position inside `s` where to start counting in bytes + * * end - The position where to stop counting + * + * # Return value + * + * The number of Unicode characters in `s` between the given indices. + */ +pub fn count_chars(s: &str, start: uint, end: uint) -> uint { + assert!(s.is_char_boundary(start)); + assert!(s.is_char_boundary(end)); + let mut i = start; + let mut len = 0u; + while i < end { + let next = s.char_range_at(i).next; + len += 1u; + i = next; + } + return len; +} + +/// Counts the number of bytes taken by the first `n` chars in `s` +/// starting from `start`. +pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint { + assert!(is_char_boundary(s, start)); + let mut end = start; + let mut cnt = n; + let l = s.len(); + while cnt > 0u { + assert!(end < l); + let next = s.char_range_at(end).next; + cnt -= 1u; + end = next; + } + end - start +} + /// Given a first byte, determine how many bytes are in this UTF-8 character pub fn utf8_char_width(b: u8) -> uint { let byte: uint = b as uint; @@ -1034,7 +1101,8 @@ pub mod raw { /// Create a Rust string from a null-terminated *u8 buffer pub unsafe fn from_buf(buf: *u8) -> ~str { - let mut (curr, i) = (buf, 0u); + let mut curr = buf; + let mut i = 0u; while *curr != 0u8 { i += 1u; curr = ptr::offset(buf, i); diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index 30ad4ee2a8945..62386075ec0df 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -641,7 +641,9 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { let child_data = Cell::new((child_arc, ancestors)); let result: ~fn() = || { // Agh. Get move-mode items into the closure. FIXME (#2829) - let mut (child_arc, ancestors) = child_data.take(); + let (child_arc, ancestors) = child_data.take(); + let mut child_arc = child_arc; + let mut ancestors = ancestors; // Child task runs this code. // Even if the below code fails to kick the child off, we must diff --git a/src/libstd/to_str.rs b/src/libstd/to_str.rs index bfda92d46a284..8c029f4eec94c 100644 --- a/src/libstd/to_str.rs +++ b/src/libstd/to_str.rs @@ -53,7 +53,8 @@ impl ToStr for (A,) { impl ToStr for HashMap { #[inline(always)] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"{", true); + let mut acc = ~"{"; + let mut first = true; for self.each |key, value| { if first { first = false; @@ -73,7 +74,8 @@ impl ToStr for HashMap { impl ToStr for HashSet { #[inline(always)] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"{", true); + let mut acc = ~"{"; + let mut first = true; for self.each |element| { if first { first = false; @@ -121,7 +123,8 @@ impl ToStr for (A, B, C) { impl<'self,A:ToStr> ToStr for &'self [A] { #[inline(always)] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"[", true); + let mut acc = ~"["; + let mut first = true; for self.each |elt| { if first { first = false; @@ -139,7 +142,8 @@ impl<'self,A:ToStr> ToStr for &'self [A] { impl ToStr for ~[A] { #[inline(always)] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"[", true); + let mut acc = ~"["; + let mut first = true; for self.each |elt| { if first { first = false; @@ -157,7 +161,8 @@ impl ToStr for ~[A] { impl ToStr for @[A] { #[inline(always)] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"[", true); + let mut acc = ~"["; + let mut first = true; for self.each |elt| { if first { first = false; diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 19233c533481e..670d0fda44471 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -739,7 +739,8 @@ pub fn truncate(v: &mut ~[T], newlen: uint) { pub fn dedup(v: &mut ~[T]) { unsafe { if v.len() < 1 { return; } - let mut (last_written, next_to_read) = (0, 1); + let mut last_written = 0; + let mut next_to_read = 1; do as_const_buf(*v) |p, ln| { // We have a mutable reference to v, so we can make arbitrary // changes. (cf. push and pop) @@ -1229,7 +1230,8 @@ pub fn bsearch_elem(v: &[T], x: &T) -> Option { * Convert a vector of pairs into a pair of vectors, by reference. As unzip(). */ pub fn unzip_slice(v: &[(T, U)]) -> (~[T], ~[U]) { - let mut (ts, us) = (~[], ~[]); + let mut ts = ~[]; + let mut us = ~[]; for each(v) |p| { let (t, u) = *p; ts.push(t); @@ -1247,7 +1249,8 @@ pub fn unzip_slice(v: &[(T, U)]) -> (~[T], ~[U]) { * of the i-th tuple of the input vector. */ pub fn unzip(v: ~[(T, U)]) -> (~[T], ~[U]) { - let mut (ts, us) = (~[], ~[]); + let mut ts = ~[]; + let mut us = ~[]; do consume(v) |_i, p| { let (t, u) = p; ts.push(t); diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index d4aa922931949..e2d1b037d3bf5 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -622,6 +622,15 @@ pub enum Privacy { Public } +/// Returns true if the given pattern consists solely of an identifier +/// and false otherwise. +pub fn pat_is_ident(pat: @ast::pat) -> bool { + match pat.node { + ast::pat_ident(*) => true, + _ => false, + } +} + // HYGIENE FUNCTIONS /// Construct an identifier with the given name and an empty context: diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index cc7b7fab07e83..9ab94baa58b97 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -65,6 +65,7 @@ pub enum ObsoleteSyntax { ObsoleteFixedLengthVectorType, ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl, + ObsoleteMutWithMultipleBindings, } impl to_bytes::IterBytes for ObsoleteSyntax { @@ -230,6 +231,11 @@ impl Parser { "instead of e.g. `let a = 1, b = 2`, write \ `let (a, b) = (1, 2)`." ), + ObsoleteMutWithMultipleBindings => ( + "`mut` with multiple bindings", + "use multiple local declarations instead of e.g. `let mut \ + (x, y) = ...`." + ), }; self.report(sp, kind, kind_str, desc); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c757d0b04fb8a..28f06c147c0a2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -85,7 +85,8 @@ use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer}; use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod}; use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType}; use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl}; -use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident, is_ident_or_path}; +use parse::obsolete::{ObsoleteMutWithMultipleBindings}; +use parse::token::{can_begin_expr, get_ident_interner, is_ident, is_ident_or_path}; use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents, token_to_binop}; use parse::token; use parse::{new_sub_parser_from_file, next_node_id, ParseSess}; @@ -824,6 +825,11 @@ impl Parser { self.parse_arg_mode(); is_mutbl = self.eat_keyword(keywords::Mut); let pat = self.parse_pat(); + + if is_mutbl && !ast_util::pat_is_ident(pat) { + self.obsolete(*self.span, ObsoleteMutWithMultipleBindings) + } + self.expect(&token::COLON); pat } else { @@ -2542,6 +2548,11 @@ impl Parser { fn parse_local(&self, is_mutbl: bool) -> @local { let lo = self.span.lo; let pat = self.parse_pat(); + + if is_mutbl && !ast_util::pat_is_ident(pat) { + self.obsolete(*self.span, ObsoleteMutWithMultipleBindings) + } + let mut ty = @Ty { id: self.get_id(), node: ty_infer, @@ -4402,7 +4413,8 @@ impl Parser { let mut attrs = vec::append(first_item_attrs, self.parse_outer_attributes()); // First, parse view items. - let mut (view_items, items) = (~[], ~[]); + let mut view_items = ~[]; + let mut items = ~[]; let mut done = false; // I think this code would probably read better as a single // loop with a mutable three-state-variable (for extern mods, diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 70f56f5c5a399..b79ecd03c0c68 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -23,7 +23,10 @@ fn main() { for range(0, h) |y| { let y = y as f64; for range(0, w) |x| { - let mut (Zr, Zi, Tr, Ti) = (0f64, 0f64, 0f64, 0f64); + let mut Zr = 0f64; + let mut Zi = 0f64; + let mut Tr = 0f64; + let mut Ti = 0f64; let Cr = 2.0 * (x as f64) / (w as f64) - 1.5; let Ci = 2.0 * (y as f64) / (h as f64) - 1.0; diff --git a/src/test/compile-fail/kindck-destructor-owned.rs b/src/test/compile-fail/kindck-destructor-owned.rs index 4c957d6bce4c5..fcab5551538cc 100644 --- a/src/test/compile-fail/kindck-destructor-owned.rs +++ b/src/test/compile-fail/kindck-destructor-owned.rs @@ -2,7 +2,7 @@ struct Foo { f: @mut int, } -impl Drop for Foo { //~ ERROR cannot implement a destructor on a struct that is not Send +impl Drop for Foo { //~ ERROR cannot implement a destructor on a structure that does not satisfy Send fn finalize(&self) { *self.f = 10; } diff --git a/src/test/compile-fail/kindck-nonsendable-1.rs b/src/test/compile-fail/kindck-nonsendable-1.rs index 928abae242383..406f9e3671126 100644 --- a/src/test/compile-fail/kindck-nonsendable-1.rs +++ b/src/test/compile-fail/kindck-nonsendable-1.rs @@ -12,7 +12,7 @@ fn foo(_x: @uint) {} fn main() { let x = @3u; - let _: ~fn() = || foo(x); //~ ERROR value has non-owned type `@uint` - let _: ~fn() = || foo(x); //~ ERROR value has non-owned type `@uint` - let _: ~fn() = || foo(x); //~ ERROR value has non-owned type `@uint` + let _: ~fn() = || foo(x); //~ ERROR value has non-sendable type `@uint` + let _: ~fn() = || foo(x); //~ ERROR value has non-sendable type `@uint` + let _: ~fn() = || foo(x); //~ ERROR value has non-sendable type `@uint` } diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs index 5e18a40a99c80..ca053c82aa58f 100644 --- a/src/test/compile-fail/no-send-res-ports.rs +++ b/src/test/compile-fail/no-send-res-ports.rs @@ -32,7 +32,7 @@ fn main() { let x = Cell::new(foo(Port(@()))); do task::spawn { - let y = x.take(); //~ ERROR value has non-owned type + let y = x.take(); //~ ERROR value has non-sendable type error!(y); } } diff --git a/src/test/compile-fail/non_owned-enum.rs b/src/test/compile-fail/non_owned-enum.rs index 6068b7f173030..20b571ad61410 100644 --- a/src/test/compile-fail/non_owned-enum.rs +++ b/src/test/compile-fail/non_owned-enum.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[non_owned] +#[non_sendable] enum Foo { A } fn bar(_: T) {} diff --git a/src/test/compile-fail/non_owned-struct.rs b/src/test/compile-fail/non_owned-struct.rs index b6f29df05752d..d4b8e6755a126 100644 --- a/src/test/compile-fail/non_owned-struct.rs +++ b/src/test/compile-fail/non_owned-struct.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[non_owned] +#[non_sendable] struct Foo { a: int } fn bar(_: T) {} diff --git a/src/test/run-pass/let-destruct-fresh-mem.rs b/src/test/run-pass/let-destruct-fresh-mem.rs index 500502320df0f..2615396653d3a 100644 --- a/src/test/run-pass/let-destruct-fresh-mem.rs +++ b/src/test/run-pass/let-destruct-fresh-mem.rs @@ -13,7 +13,9 @@ struct A { a: int } pub fn main() { let u = X {x: 10, y: @A {a: 20}}; - let mut X {x: x, y: @A {a: a}} = u; + let X {x: x, y: @A {a: a}} = u; + let mut x = x; + let mut a = a; x = 100; a = 100; assert_eq!(x, 100); diff --git a/src/test/run-pass/pipe-peek.rs b/src/test/run-pass/pipe-peek.rs index 8d8c96c6f5140..cbc822060cec2 100644 --- a/src/test/run-pass/pipe-peek.rs +++ b/src/test/run-pass/pipe-peek.rs @@ -22,7 +22,9 @@ proto! oneshot ( ) pub fn main() { - let mut (p, c) = oneshot::init(); + let (p, c) = oneshot::init(); + let mut p = p; + let mut c = c; assert!(!pipes::peek(&mut p)); From 2b0cdd242625966cc96a6c0db2e366a16a9f1117 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 7 Jun 2013 15:47:05 -0700 Subject: [PATCH 06/13] libsyntax: Fix merge fallout --- src/libsyntax/parse/parser.rs | 6 ++- src/libsyntax/parse/token.rs | 72 +++++++++++++++++------------------ 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 28f06c147c0a2..b115667ec2f5f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -86,8 +86,10 @@ use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod}; use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType}; use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl}; use parse::obsolete::{ObsoleteMutWithMultipleBindings}; -use parse::token::{can_begin_expr, get_ident_interner, is_ident, is_ident_or_path}; -use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents, token_to_binop}; +use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident}; +use parse::token::{is_ident_or_path}; +use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents}; +use parse::token::{token_to_binop}; use parse::token; use parse::{new_sub_parser_from_file, next_node_id, ParseSess}; use opt_vec; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 2436e0e5c69bb..7610175a37415 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -614,42 +614,42 @@ pub mod keywords { impl Keyword { pub fn to_ident(&self) -> ident { match *self { - As => ident { repr: 35, ctxt: 0 }, - Break => ident { repr: 36, ctxt: 0 }, - Freeze => ident { repr: 37, ctxt: 0 }, - Copy => ident { repr: 38, ctxt: 0 }, - Do => ident { repr: 39, ctxt: 0 }, - Else => ident { repr: 41, ctxt: 0 }, - Enum => ident { repr: 42, ctxt: 0 }, - Extern => ident { repr: 43, ctxt: 0 }, - False => ident { repr: 44, ctxt: 0 }, - Fn => ident { repr: 45, ctxt: 0 }, - For => ident { repr: 46, ctxt: 0 }, - If => ident { repr: 47, ctxt: 0 }, - Impl => ident { repr: 48, ctxt: 0 }, - Let => ident { repr: 49, ctxt: 0 }, - __Log => ident { repr: 50, ctxt: 0 }, - Loop => ident { repr: 51, ctxt: 0 }, - Match => ident { repr: 52, ctxt: 0 }, - Mod => ident { repr: 53, ctxt: 0 }, - Mut => ident { repr: 54, ctxt: 0 }, - Once => ident { repr: 55, ctxt: 0 }, - Priv => ident { repr: 56, ctxt: 0 }, - Pub => ident { repr: 57, ctxt: 0 }, - Pure => ident { repr: 58, ctxt: 0 }, - Ref => ident { repr: 59, ctxt: 0 }, - Return => ident { repr: 60, ctxt: 0 }, - Static => ident { repr: 29, ctxt: 0 }, - Self => ident { repr: 8, ctxt: 0 }, - Struct => ident { repr: 61, ctxt: 0 }, - Super => ident { repr: 62, ctxt: 0 }, - True => ident { repr: 63, ctxt: 0 }, - Trait => ident { repr: 64, ctxt: 0 }, - Type => ident { repr: 65, ctxt: 0 }, - Unsafe => ident { repr: 66, ctxt: 0 }, - Use => ident { repr: 67, ctxt: 0 }, - While => ident { repr: 68, ctxt: 0 }, - Be => ident { repr: 69, ctxt: 0 }, + As => ident { name: 35, ctxt: 0 }, + Break => ident { name: 36, ctxt: 0 }, + Freeze => ident { name: 37, ctxt: 0 }, + Copy => ident { name: 38, ctxt: 0 }, + Do => ident { name: 39, ctxt: 0 }, + Else => ident { name: 41, ctxt: 0 }, + Enum => ident { name: 42, ctxt: 0 }, + Extern => ident { name: 43, ctxt: 0 }, + False => ident { name: 44, ctxt: 0 }, + Fn => ident { name: 45, ctxt: 0 }, + For => ident { name: 46, ctxt: 0 }, + If => ident { name: 47, ctxt: 0 }, + Impl => ident { name: 48, ctxt: 0 }, + Let => ident { name: 49, ctxt: 0 }, + __Log => ident { name: 50, ctxt: 0 }, + Loop => ident { name: 51, ctxt: 0 }, + Match => ident { name: 52, ctxt: 0 }, + Mod => ident { name: 53, ctxt: 0 }, + Mut => ident { name: 54, ctxt: 0 }, + Once => ident { name: 55, ctxt: 0 }, + Priv => ident { name: 56, ctxt: 0 }, + Pub => ident { name: 57, ctxt: 0 }, + Pure => ident { name: 58, ctxt: 0 }, + Ref => ident { name: 59, ctxt: 0 }, + Return => ident { name: 60, ctxt: 0 }, + Static => ident { name: 29, ctxt: 0 }, + Self => ident { name: 8, ctxt: 0 }, + Struct => ident { name: 61, ctxt: 0 }, + Super => ident { name: 62, ctxt: 0 }, + True => ident { name: 63, ctxt: 0 }, + Trait => ident { name: 64, ctxt: 0 }, + Type => ident { name: 65, ctxt: 0 }, + Unsafe => ident { name: 66, ctxt: 0 }, + Use => ident { name: 67, ctxt: 0 }, + While => ident { name: 68, ctxt: 0 }, + Be => ident { name: 69, ctxt: 0 }, } } } From c4557f3256067745ba8d309bf2423765ea1ec15d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 7 Jun 2013 19:59:32 -0700 Subject: [PATCH 07/13] librustc: Add a small vector optimization for GEPi. Shaves a second off trans, I think? --- src/librustc/middle/trans/build.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 8ac47ed135ad4..1c2581b9af96a 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -605,12 +605,21 @@ pub fn GEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef { // Simple wrapper around GEP that takes an array of ints and wraps them // in C_i32() -// -// FIXME #6571: Use a small-vector optimization to avoid allocations here. +#[inline] pub fn GEPi(cx: block, base: ValueRef, ixs: &[uint]) -> ValueRef { - let v = do vec::map(ixs) |i| { C_i32(*i as i32) }; - count_insn(cx, "gepi"); - return InBoundsGEP(cx, base, v); + // Small vector optimization. This should catch 100% of the cases that + // we care about. + if ixs.len() < 16 { + let mut small_vec = [ C_i32(0), ..16 ]; + for ixs.eachi |i, &ix| { + small_vec[i] = C_i32(ix as i32) + } + InBoundsGEP(cx, base, small_vec.slice(0, ixs.len())) + } else { + let v = do vec::map(ixs) |i| { C_i32(*i as i32) }; + count_insn(cx, "gepi"); + InBoundsGEP(cx, base, v) + } } pub fn InBoundsGEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> From 770b64957653699ca5a3077786d99c379ef28353 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 10 Jun 2013 15:55:51 -0700 Subject: [PATCH 08/13] libstd: Fix merge fallout. --- src/libstd/str.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 2b91d04d8b056..0c630ea4fe150 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -356,7 +356,8 @@ impl<'self> Iterator<(uint, uint)> for StrMatchesIndexIterator<'self> { fn next(&mut self) -> Option<(uint, uint)> { // See Issue #1932 for why this is a naive search let (h_len, n_len) = (self.haystack.len(), self.needle.len()); - let mut (match_start, match_i) = (0, 0); + let mut match_start = 0; + let mut match_i = 0; while self.position < h_len { if self.haystack[self.position] == self.needle[match_i] { @@ -948,7 +949,7 @@ pub fn count_chars(s: &str, start: uint, end: uint) -> uint { /// Counts the number of bytes taken by the first `n` chars in `s` /// starting from `start`. pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint { - assert!(is_char_boundary(s, start)); + assert!(s.is_char_boundary(start)); let mut end = start; let mut cnt = n; let l = s.len(); From c837276b66d8d1556567c5009a6d116c904650a6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 10 Jun 2013 19:42:28 -0700 Subject: [PATCH 09/13] libsyntax: Remove "copy" pattern bindings from the language --- src/libsyntax/parse/obsolete.rs | 5 +++++ src/libsyntax/parse/parser.rs | 4 ++-- src/test/compile-fail/rcmut-not-const-and-not-owned.rs | 8 ++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 9ab94baa58b97..155d33792c01c 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -66,6 +66,7 @@ pub enum ObsoleteSyntax { ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl, ObsoleteMutWithMultipleBindings, + ObsoletePatternCopyKeyword, } impl to_bytes::IterBytes for ObsoleteSyntax { @@ -236,6 +237,10 @@ impl Parser { "use multiple local declarations instead of e.g. `let mut \ (x, y) = ...`." ), + ObsoletePatternCopyKeyword => ( + "`copy` in patterns", + "`copy` in patterns no longer has any effect" + ), }; self.report(sp, kind, kind_str, desc); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b115667ec2f5f..53d93ff8452f5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -86,6 +86,7 @@ use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod}; use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType}; use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl}; use parse::obsolete::{ObsoleteMutWithMultipleBindings}; +use parse::obsolete::{ObsoletePatternCopyKeyword}; use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident}; use parse::token::{is_ident_or_path}; use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents}; @@ -2427,8 +2428,7 @@ impl Parser { pat = self.parse_pat_ident(bind_by_ref(mutbl)); } else if self.eat_keyword(keywords::Copy) { // parse copy pat - self.warn("copy keyword in patterns no longer has any effect, \ - remove it"); + self.obsolete(*self.span, ObsoletePatternCopyKeyword); pat = self.parse_pat_ident(bind_infer); } else { let can_be_enum_or_struct; diff --git a/src/test/compile-fail/rcmut-not-const-and-not-owned.rs b/src/test/compile-fail/rcmut-not-const-and-not-owned.rs index 9e7236a67d96f..45cb137b08459 100644 --- a/src/test/compile-fail/rcmut-not-const-and-not-owned.rs +++ b/src/test/compile-fail/rcmut-not-const-and-not-owned.rs @@ -10,11 +10,11 @@ extern mod extra; -fn o(_: &T) {} -fn c(_: &T) {} +fn o(_: &T) {} +fn c(_: &T) {} fn main() { let x = extra::rc::rc_mut_from_owned(0); - o(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut`, which does not fulfill `Owned` - c(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut`, which does not fulfill `Const` + o(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut`, which does not fulfill `Send` + c(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut`, which does not fulfill `Freeze` } From 856bb340b82937ca696822d8aedabe87b624bdf7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 11 Jun 2013 19:13:42 -0700 Subject: [PATCH 10/13] librustc: Remove the broken overloaded assign-ops from the language. They evaluated the receiver twice. They should be added back with `AddAssign`, `SubAssign`, etc., traits. --- doc/tutorial.md | 4 +- src/compiletest/errors.rs | 2 +- src/compiletest/runtest.rs | 8 +-- src/libextra/arena.rs | 27 ++++----- src/libextra/bitv.rs | 12 +++- src/libextra/getopts.rs | 50 ++++++++++------ src/libextra/json.rs | 22 +++---- src/libextra/md4.rs | 6 +- src/libextra/net_url.rs | 8 +-- src/libextra/num/bigint.rs | 4 +- src/libextra/sha1.rs | 4 +- src/libextra/time.rs | 2 +- src/librustc/back/link.rs | 30 +++++----- src/librustc/lib/llvm.rs | 8 ++- src/librustc/metadata/encoder.rs | 2 +- src/librustc/metadata/tydecode.rs | 4 +- src/librustc/middle/resolve.rs | 8 ++- src/librustc/middle/trans/asm.rs | 10 ++-- src/librustc/middle/trans/build.rs | 8 +-- src/librustc/middle/trans/common.rs | 9 ++- src/librustc/middle/trans/shape.rs | 5 +- src/librustc/middle/ty.rs | 6 +- src/librustc/middle/typeck/check/mod.rs | 56 ++++++++++++++++-- src/librustdoc/markdown_pass.rs | 6 +- src/librustdoc/markdown_writer.rs | 4 +- src/librustdoc/page_pass.rs | 2 +- src/librustdoc/sectionalize_pass.rs | 4 +- src/librusti/rusti.rc | 13 +++-- src/libstd/hash.rs | 7 ++- src/libstd/num/num.rs | 6 +- src/libstd/num/strconv.rs | 16 +++--- src/libstd/path.rs | 16 ++++-- src/libsyntax/diagnostic.rs | 25 ++++---- src/libsyntax/ext/concat_idents.rs | 3 +- src/libsyntax/ext/pipes/pipec.rs | 57 ++++++++++--------- src/libsyntax/parse/attr.rs | 16 +++--- src/libsyntax/parse/comments.rs | 6 +- src/libsyntax/parse/common.rs | 8 +-- src/libsyntax/parse/lexer.rs | 8 +-- src/libsyntax/parse/parser.rs | 8 ++- src/libsyntax/parse/token.rs | 4 +- src/libsyntax/print/pp.rs | 8 ++- src/test/bench/core-std.rs | 5 +- src/test/bench/shootout-chameneos-redux.rs | 4 +- src/test/bench/shootout-fasta.rs | 2 +- src/test/bench/shootout-k-nucleotide-pipes.rs | 2 +- src/test/bench/sudoku.rs | 4 +- src/test/compile-fail/issue-2149.rs | 2 +- src/test/run-fail/issue-3029.rs | 4 +- src/test/run-pass/istr.rs | 8 +-- src/test/run-pass/liveness-move-in-loop.rs | 2 +- src/test/run-pass/match-join.rs | 2 +- src/test/run-pass/monad.rs | 4 +- src/test/run-pass/mutable-alias-vec.rs | 4 +- src/test/run-pass/operator-overloading.rs | 2 +- src/test/run-pass/shadow.rs | 2 +- src/test/run-pass/static-impl.rs | 4 +- src/test/run-pass/str-append.rs | 2 +- src/test/run-pass/str-growth.rs | 6 +- src/test/run-pass/trait-generic.rs | 4 +- src/test/run-pass/vec-growth.rs | 8 +-- src/test/run-pass/while-prelude-drop.rs | 2 +- 62 files changed, 348 insertions(+), 237 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index a458036116665..f206d16258cee 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1281,9 +1281,9 @@ let your_crayons = ~[BananaMania, Beaver, Bittersweet]; // Add two vectors to create a new one let our_crayons = my_crayons + your_crayons; -// += will append to a vector, provided it lives in a mutable slot +// .push_all() will append to a vector, provided it lives in a mutable slot let mut my_crayons = my_crayons; -my_crayons += your_crayons; +my_crayons.push_all(your_crayons); ~~~~ > ***Note:*** The above examples of vector addition use owned diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index cdc0defcbcab0..4649d4dfc3c4b 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -21,7 +21,7 @@ pub fn load_errors(testfile: &Path) -> ~[ExpectedError] { let mut line_num = 1u; while !rdr.eof() { let ln = rdr.read_line(); - error_patterns += parse_expected(line_num, ln); + error_patterns.push_all_move(parse_expected(line_num, ln)); line_num += 1u; } return error_patterns; diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index c92084781287a..33b9bc56bd9cc 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -228,8 +228,8 @@ actual:\n\ ~"-L", config.build_base.to_str(), ~"-L", aux_output_dir_name(config, testfile).to_str()]; - args += split_maybe_args(&config.rustcflags); - args += split_maybe_args(&props.compile_flags); + args.push_all_move(split_maybe_args(&config.rustcflags)); + args.push_all_move(split_maybe_args(&props.compile_flags)); return ProcArgs {prog: config.rustc_path.to_str(), args: args}; } } @@ -584,8 +584,8 @@ fn make_compile_args(config: &config, props: &TestProps, extras: ~[~str], ~"-o", xform(config, testfile).to_str(), ~"-L", config.build_base.to_str()] + extras; - args += split_maybe_args(&config.rustcflags); - args += split_maybe_args(&props.compile_flags); + args.push_all_move(split_maybe_args(&config.rustcflags)); + args.push_all_move(split_maybe_args(&props.compile_flags)); return ProcArgs {prog: config.rustc_path.to_str(), args: args}; } diff --git a/src/libextra/arena.rs b/src/libextra/arena.rs index 2926d5958f16c..20412f0518eaf 100644 --- a/src/libextra/arena.rs +++ b/src/libextra/arena.rs @@ -182,20 +182,18 @@ impl Arena { #[inline(always)] fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 { unsafe { - // XXX: Borrow check - let head = transmute_mut_region(&mut self.pod_head); - - let start = round_up_to(head.fill, align); + let this = transmute_mut_region(self); + let start = round_up_to(this.pod_head.fill, align); let end = start + n_bytes; - if end > at_vec::capacity(head.data) { - return self.alloc_pod_grow(n_bytes, align); + if end > at_vec::capacity(this.pod_head.data) { + return this.alloc_pod_grow(n_bytes, align); } - head.fill = end; + this.pod_head.fill = end; //debug!("idx = %u, size = %u, align = %u, fill = %u", // start, n_bytes, align, head.fill); - ptr::offset(vec::raw::to_ptr(head.data), start) + ptr::offset(vec::raw::to_ptr(this.pod_head.data), start) } } @@ -227,21 +225,19 @@ impl Arena { fn alloc_nonpod_inner(&mut self, n_bytes: uint, align: uint) -> (*u8, *u8) { unsafe { - let head = transmute_mut_region(&mut self.head); - - let tydesc_start = head.fill; - let after_tydesc = head.fill + sys::size_of::<*TypeDesc>(); + let tydesc_start = self.head.fill; + let after_tydesc = self.head.fill + sys::size_of::<*TypeDesc>(); let start = round_up_to(after_tydesc, align); let end = start + n_bytes; - if end > at_vec::capacity(head.data) { + if end > at_vec::capacity(self.head.data) { return self.alloc_nonpod_grow(n_bytes, align); } - head.fill = round_up_to(end, sys::pref_align_of::<*TypeDesc>()); + self.head.fill = round_up_to(end, sys::pref_align_of::<*TypeDesc>()); //debug!("idx = %u, size = %u, align = %u, fill = %u", // start, n_bytes, align, head.fill); - let buf = vec::raw::to_ptr(head.data); + let buf = vec::raw::to_ptr(self.head.data); return (ptr::offset(buf, tydesc_start), ptr::offset(buf, start)); } } @@ -277,7 +273,6 @@ impl Arena { return this.alloc_pod(op); } // XXX: Borrow check - let this = transmute_mut_region(self); this.alloc_nonpod(op) } } diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs index e3a15f76c786b..75077a06ea960 100644 --- a/src/libextra/bitv.rs +++ b/src/libextra/bitv.rs @@ -476,9 +476,15 @@ impl Bitv { * character is either '0' or '1'. */ pub fn to_str(&self) -> ~str { - let mut rs = ~""; - for self.each() |i| { if i { rs += "1"; } else { rs += "0"; } }; - rs + let mut rs = ~""; + for self.each() |i| { + if i { + rs.push_char('1'); + } else { + rs.push_char('0'); + } + }; + rs } diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index f07a2f0c25bff..7ff4cd0e8c14a 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -606,33 +606,47 @@ pub mod groups { let mut row = " ".repeat(4); // short option - row += match short_name.len() { - 0 => ~"", - 1 => ~"-" + short_name + " ", + match short_name.len() { + 0 => {} + 1 => { + row.push_char('-'); + row.push_str(short_name); + row.push_char(' '); + } _ => fail!("the short name should only be 1 ascii char long"), - }; + } // long option - row += match long_name.len() { - 0 => ~"", - _ => ~"--" + long_name + " ", - }; + match long_name.len() { + 0 => {} + _ => { + row.push_str("--"); + row.push_str(long_name); + row.push_char(' '); + } + } // arg - row += match hasarg { - No => ~"", - Yes => hint, - Maybe => ~"[" + hint + "]", - }; + match hasarg { + No => {} + Yes => row.push_str(hint), + Maybe => { + row.push_char('['); + row.push_str(hint); + row.push_char(']'); + } + } // FIXME: #5516 // here we just need to indent the start of the description let rowlen = row.len(); - row += if rowlen < 24 { - " ".repeat(24 - rowlen) + if rowlen < 24 { + for (24 - rowlen).times { + row.push_char(' ') + } } else { - copy desc_sep - }; + row.push_str(desc_sep) + } // Normalize desc to contain words separated by one space character let mut desc_normalized_whitespace = ~""; @@ -649,7 +663,7 @@ pub mod groups { // FIXME: #5516 // wrapped description - row += desc_rows.connect(desc_sep); + row.push_str(desc_rows.connect(desc_sep)); row }); diff --git a/src/libextra/json.rs b/src/libextra/json.rs index 1e9ec48aff32d..ef7aef3946152 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -61,25 +61,27 @@ fn escape_str(s: &str) -> ~str { let mut escaped = ~"\""; for s.iter().advance |c| { match c { - '"' => escaped += "\\\"", - '\\' => escaped += "\\\\", - '\x08' => escaped += "\\b", - '\x0c' => escaped += "\\f", - '\n' => escaped += "\\n", - '\r' => escaped += "\\r", - '\t' => escaped += "\\t", - _ => escaped += str::from_char(c) + '"' => escaped.push_str("\\\""), + '\\' => escaped.push_str("\\\\"), + '\x08' => escaped.push_str("\\b"), + '\x0c' => escaped.push_str("\\f"), + '\n' => escaped.push_str("\\n"), + '\r' => escaped.push_str("\\r"), + '\t' => escaped.push_str("\\t"), + _ => escaped.push_char(c), } }; - escaped += "\""; + escaped.push_char('"'); escaped } fn spaces(n: uint) -> ~str { let mut ss = ~""; - for n.times { ss.push_str(" "); } + for n.times { + ss.push_str(" "); + } return ss; } diff --git a/src/libextra/md4.rs b/src/libextra/md4.rs index 2534fedd9611f..3be7394b46d0b 100644 --- a/src/libextra/md4.rs +++ b/src/libextra/md4.rs @@ -119,8 +119,10 @@ pub fn md4_str(msg: &[u8]) -> ~str { let mut i = 0u32; while i < 4u32 { let byte = (u >> (i * 8u32)) as u8; - if byte <= 16u8 { result += "0"; } - result += uint::to_str_radix(byte as uint, 16u); + if byte <= 16u8 { + result.push_char('0') + } + result.push_str(uint::to_str_radix(byte as uint, 16u)); i += 1u32; } } diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index 30ec0967f278e..83a83b2ebab2d 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -94,10 +94,10 @@ fn encode_inner(s: &str, full_url: bool) -> ~str { out.push_char(ch); } - _ => out += fmt!("%%%X", ch as uint) + _ => out.push_str(fmt!("%%%X", ch as uint)) } } else { - out += fmt!("%%%X", ch as uint); + out.push_str(fmt!("%%%X", ch as uint)); } } } @@ -193,7 +193,7 @@ fn encode_plus(s: &str) -> ~str { out.push_char(ch); } ' ' => out.push_char('+'), - _ => out += fmt!("%%%X", ch as uint) + _ => out.push_str(fmt!("%%%X", ch as uint)) } } @@ -219,7 +219,7 @@ pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str { first = false; } - out += fmt!("%s=%s", key, encode_plus(*value)); + out.push_str(fmt!("%s=%s", key, encode_plus(*value))); } } diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 93ffc4a7e876d..e05dae11a6c13 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -512,11 +512,11 @@ impl ToStrRadix for BigUint { let mut m = n; while m > divider { let (d, m0) = m.div_mod_floor(÷r); - result += [m0.to_uint() as BigDigit]; + result.push(m0.to_uint() as BigDigit); m = d; } if !m.is_zero() { - result += [m.to_uint() as BigDigit]; + result.push(m.to_uint() as BigDigit); } return result; } diff --git a/src/libextra/sha1.rs b/src/libextra/sha1.rs index 03ceded007301..57d2d75c1b7f3 100644 --- a/src/libextra/sha1.rs +++ b/src/libextra/sha1.rs @@ -254,9 +254,9 @@ pub fn sha1() -> @Sha1 { for rr.each |b| { let hex = uint::to_str_radix(*b as uint, 16u); if hex.len() == 1 { - s += "0"; + s.push_char('0') } - s += hex; + s.push_str(hex) } return s; } diff --git a/src/libextra/time.rs b/src/libextra/time.rs index caaa2994405e0..d469cd526613f 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -850,7 +850,7 @@ priv fn do_strftime(format: &str, tm: &Tm) -> ~str { do io::with_str_reader(format) |rdr| { while !rdr.eof() { match rdr.read_char() { - '%' => buf += parse_type(rdr.read_char(), tm), + '%' => buf.push_str(parse_type(rdr.read_char(), tm)), ch => buf.push_char(ch) } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 3c8705b4ee936..5dfc2f5fe3ea4 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -639,15 +639,15 @@ pub fn sanitize(s: &str) -> ~str { for s.iter().advance |c| { match c { // Escape these with $ sequences - '@' => result += "$SP$", - '~' => result += "$UP$", - '*' => result += "$RP$", - '&' => result += "$BP$", - '<' => result += "$LT$", - '>' => result += "$GT$", - '(' => result += "$LP$", - ')' => result += "$RP$", - ',' => result += "$C$", + '@' => result.push_str("$SP$"), + '~' => result.push_str("$UP$"), + '*' => result.push_str("$RP$"), + '&' => result.push_str("$BP$"), + '<' => result.push_str("$LT$"), + '>' => result.push_str("$GT$"), + '(' => result.push_str("$LP$"), + ')' => result.push_str("$RP$"), + ',' => result.push_str("$C$"), // '.' doesn't occur in types and functions, so reuse it // for ':' @@ -683,12 +683,14 @@ pub fn mangle(sess: Session, ss: path) -> ~str { let mut n = ~"_ZN"; // Begin name-sequence. for ss.each |s| { - match *s { path_name(s) | path_mod(s) => { - let sani = sanitize(sess.str_of(s)); - n += fmt!("%u%s", sani.len(), sani); - } } + match *s { + path_name(s) | path_mod(s) => { + let sani = sanitize(*sess.str_of(s)); + n.push_str(fmt!("%u%s", sani.len(), sani)); + } + } } - n += "E"; // End name-sequence. + n.push_char('E'); // End name-sequence. n } diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index f6beb078e46f5..27a59eba8e1ed 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -2013,8 +2013,12 @@ pub fn type_to_str_inner(names: @TypeNames, outer0: &[TypeRef], ty: TypeRef) let mut s = ~""; let mut first: bool = true; for tys.each |t| { - if first { first = false; } else { s += ", "; } - s += type_to_str_inner(names, outer, *t); + if first { + first = false + } else { + s.push_str(", ") + } + s.push_str(type_to_str_inner(names, outer, *t)); } // [Note at-str] FIXME #2543: Could rewrite this without the copy, // but need better @str support. diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index afa76eae4cfb5..2518bf95a97e6 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -970,7 +970,7 @@ fn encode_info_for_item(ecx: @EncodeContext, // >:-< let mut impl_path = vec::append(~[], path); - impl_path += [ast_map::path_name(item.ident)]; + impl_path.push(ast_map::path_name(item.ident)); for methods.each |m| { index.push(entry {val: m.id, pos: ebml_w.writer.tell()}); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 6cab5ca3ddcdf..b82b9e805c421 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -262,7 +262,9 @@ fn parse_opt(st: &mut PState, f: &fn(&mut PState) -> T) -> Option { fn parse_str(st: &mut PState, term: char) -> ~str { let mut result = ~""; while peek(st) != term { - result += str::from_byte(next_byte(st)); + unsafe { + str::raw::push_byte(&mut result, next_byte(st)); + } } next(st); return result; diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 9637a32ba9f4b..89f2053c8a583 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -2076,8 +2076,12 @@ impl Resolver { let mut first = true; let mut result = ~""; for idents.each |ident| { - if first { first = false; } else { result += "::" }; - result += self.session.str_of(*ident); + if first { + first = false + } else { + result.push_str("::") + } + result.push_str(*self.session.str_of(*ident)); }; return result; } diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index d73d57efbbf72..dfc7abcbf49d6 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -93,15 +93,15 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block { if !ia.clobbers.is_empty() && !clobbers.is_empty() { clobbers = fmt!("%s,%s", ia.clobbers, clobbers); } else { - clobbers += ia.clobbers; + clobbers.push_str(*ia.clobbers); }; // Add the clobbers to our constraints list - if !clobbers.is_empty() && !constraints.is_empty() { - constraints += ","; - constraints += clobbers; + if clobbers.len() != 0 && constraints.len() != 0 { + constraints.push_char(','); + constraints.push_str(clobbers); } else { - constraints += clobbers; + constraints.push_str(clobbers); } debug!("Asm Constraints: %?", constraints); diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 1c2581b9af96a..05aee71796f7d 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -67,13 +67,13 @@ pub fn count_insn(cx: block, category: &str) { i = 0u; while i < len { i = *mm.get(&v[i]); - s += "/"; - s += v[i]; + s.push_char('/'); + s.push_str(v[i]); i += 1u; } - s += "/"; - s += category; + s.push_char('/'); + s.push_str(category); let n = match h.find(&s) { Some(&n) => n, diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index a12ce790d041b..0d411e7341b4d 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1418,9 +1418,12 @@ pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str { for p.each |e| { match *e { ast_map::path_name(s) | ast_map::path_mod(s) => { - if first { first = false; } - else { r += "::"; } - r += sess.str_of(s); + if first { + first = false + } else { + r.push_str("::") + } + r.push_str(*sess.str_of(s)); } } } diff --git a/src/librustc/middle/trans/shape.rs b/src/librustc/middle/trans/shape.rs index 6612122fd3e34..92315c6a9190d 100644 --- a/src/librustc/middle/trans/shape.rs +++ b/src/librustc/middle/trans/shape.rs @@ -66,10 +66,11 @@ Although these two functions are never called, they are here for a VERY GOOD REASON. See #3670 */ pub fn add_u16(dest: &mut ~[u8], val: u16) { - *dest += [(val & 0xffu16) as u8, (val >> 8u16) as u8]; + dest.push((val & 0xffu16) as u8); + dest.push((val >> 8u16) as u8); } pub fn add_substr(dest: &mut ~[u8], src: ~[u8]) { add_u16(&mut *dest, src.len() as u16); - *dest += src; + dest.push_all_move(src); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index afb988a07d275..c12c60b70dda6 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2120,7 +2120,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { TC_NONE, |tc, f| tc + tc_mt(cx, f.mt, cache)); if ty::has_dtor(cx, did) { - res += TC_DTOR; + res = res + TC_DTOR; } apply_tc_attr(cx, did, res) } @@ -2204,10 +2204,10 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { fn apply_tc_attr(cx: ctxt, did: def_id, mut tc: TypeContents) -> TypeContents { if has_attr(cx, did, "mutable") { - tc += TC_MUTABLE; + tc = tc + TC_MUTABLE; } if has_attr(cx, did, "non_sendable") { - tc += TC_NON_SENDABLE; + tc = tc + TC_NON_SENDABLE; } tc } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 14f251878a4d2..c018cc6b8ac45 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -214,6 +214,13 @@ impl PurityState { } } +/// Whether `check_binop` allows overloaded operators to be invoked. +#[deriving(Eq)] +enum AllowOverloadedOperatorsFlag { + AllowOverloadedOperators, + DontAllowOverloadedOperators, +} + pub struct FnCtxt { // Number of errors that had been reported when we started // checking this function. On exit, if we find that *more* errors @@ -1487,7 +1494,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, lhs: @ast::expr, rhs: @ast::expr, // Used only in the error case - expected_result: Option + expected_result: Option, + allow_overloaded_operators: AllowOverloadedOperatorsFlag ) { let tcx = fcx.ccx.tcx; @@ -1537,8 +1545,30 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } - let result_t = check_user_binop(fcx, callee_id, expr, lhs, lhs_t, op, rhs, - expected_result); + // Check for overloaded operators if allowed. + let result_t; + if allow_overloaded_operators == AllowOverloadedOperators { + result_t = check_user_binop(fcx, + callee_id, + expr, + lhs, + lhs_t, + op, + rhs, + expected_result); + } else { + fcx.type_error_message(expr.span, + |actual| { + fmt!("binary operation %s cannot be \ + applied to type `%s`", + ast_util::binop_to_str(op), + actual) + }, + lhs_t, + None); + result_t = ty::mk_err(); + } + fcx.write_ty(expr.id, result_t); if ty::type_is_error(result_t) { fcx.write_ty(rhs.id, result_t); @@ -2229,7 +2259,15 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(id, typ); } ast::expr_binary(callee_id, op, lhs, rhs) => { - check_binop(fcx, callee_id, expr, op, lhs, rhs, expected); + check_binop(fcx, + callee_id, + expr, + op, + lhs, + rhs, + expected, + AllowOverloadedOperators); + let lhs_ty = fcx.expr_ty(lhs); let rhs_ty = fcx.expr_ty(rhs); if ty::type_is_error(lhs_ty) || @@ -2242,7 +2280,15 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } ast::expr_assign_op(callee_id, op, lhs, rhs) => { - check_binop(fcx, callee_id, expr, op, lhs, rhs, expected); + check_binop(fcx, + callee_id, + expr, + op, + lhs, + rhs, + expected, + DontAllowOverloadedOperators); + let lhs_t = fcx.expr_ty(lhs); let result_t = fcx.expr_ty(expr); demand::suptype(fcx, expr.span, result_t, lhs_t); diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 2168484c84e29..9cc8c22a5aff6 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -192,11 +192,11 @@ pub fn header_name(doc: doc::ItemTag) -> ~str { let mut trait_part = ~""; for doc.trait_types.eachi |i, trait_type| { if i == 0 { - trait_part += " of "; + trait_part.push_str(" of "); } else { - trait_part += ", "; + trait_part.push_str(", "); } - trait_part += *trait_type; + trait_part.push_str(*trait_type); } fmt!("%s for %s%s", trait_part, *self_ty, bounds) } diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs index 353152763267c..a093824e453bf 100644 --- a/src/librustdoc/markdown_writer.rs +++ b/src/librustdoc/markdown_writer.rs @@ -130,7 +130,7 @@ fn generic_writer(process: ~fn(markdown: ~str)) -> Writer { let mut keep_going = true; while keep_going { match po.recv() { - Write(s) => markdown += s, + Write(s) => markdown.push_str(s), Done => keep_going = false } } @@ -214,7 +214,7 @@ fn future_writer() -> (Writer, future::Future<~str>) { let mut res = ~""; loop { match port.recv() { - Write(s) => res += s, + Write(s) => res.push_str(s), Done => break } } diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index bb5d71e8db168..8260ad8ec8c38 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -70,7 +70,7 @@ fn make_doc_from_pages(page_port: &PagePort) -> doc::Doc { loop { let val = page_port.recv(); if val.is_some() { - pages += [val.unwrap()]; + pages.push(val.unwrap()); } else { break; } diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index 8716f823848e2..5d89fbb056f21 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -115,7 +115,7 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { match parse_header(copy *line) { Some(header) => { if current_section.is_some() { - sections += [copy *current_section.get_ref()]; + sections.push(copy *current_section.get_ref()); } current_section = Some(doc::Section { header: header, @@ -146,7 +146,7 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { } if current_section.is_some() { - sections += [current_section.get()]; + sections.push(current_section.get()); } (new_desc, sections) diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 90a5a350b7fa4..0d05c990d2977 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -380,9 +380,13 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, for loaded_crates.each |crate| { let crate_path = Path(*crate); let crate_dir = crate_path.dirname(); - repl.program.record_extern(fmt!("extern mod %s;", *crate)); - if !repl.lib_search_paths.contains(&crate_dir) { - repl.lib_search_paths.push(crate_dir); + let crate_name = crate_path.filename().get(); + if !repl.view_items.contains(*crate) { + repl.view_items.push_str(fmt!("extern mod %s;\n", + crate_name)); + if !repl.lib_search_paths.contains(&crate_dir) { + repl.lib_search_paths.push(crate_dir); + } } } if loaded_crates.is_empty() { @@ -402,7 +406,8 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, if line.trim() == ":}" { end_multiline = true; } else { - multiline_cmd += line + "\n"; + multiline_cmd.push_str(line); + multiline_cmd.push_char('\n'); } } } diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index e902244578634..42c2d46b20302 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -24,6 +24,7 @@ use container::Container; use old_iter::BaseIter; use rt::io::Writer; +use str::OwnedStr; use to_bytes::IterBytes; use uint; @@ -368,7 +369,7 @@ impl Streaming for SipState { let r = self.result_bytes(); let mut s = ~""; for r.each |b| { - s += uint::to_str_radix(*b as uint, 16u); + s.push_str(uint::to_str_radix(*b as uint, 16u)); } s } @@ -470,7 +471,7 @@ mod tests { fn to_hex_str(r: &[u8, ..8]) -> ~str { let mut s = ~""; for (*r).each |b| { - s += uint::to_str_radix(*b as uint, 16u); + s.push_str(uint::to_str_radix(*b as uint, 16u)); } s } @@ -491,7 +492,7 @@ mod tests { assert!(f == i && f == v); - buf += [t as u8]; + buf.push(t as u8); stream_inc.input([t as u8]); t += 1; diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs index a9893579721c1..a6f518a7e2e6e 100644 --- a/src/libstd/num/num.rs +++ b/src/libstd/num/num.rs @@ -410,10 +410,10 @@ pub fn pow_with_uint+Mul>(radix: uint, pow let mut multiplier = cast(radix); while (my_pow > 0u) { if my_pow % 2u == 1u { - total *= multiplier; + total = total * multiplier; } - my_pow /= 2u; - multiplier *= multiplier; + my_pow = my_pow / 2u; + multiplier = multiplier * multiplier; } total } diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 3905d82cd0f5c..84a04b5c24dcb 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -229,7 +229,7 @@ pub fn to_str_bytes_common+ match char::to_digit(c, radix) { Some(digit) => { // shift accum one digit left - accum *= radix_gen; + accum = accum * radix_gen; // add/subtract current digit depending on sign if accum_positive { - accum += cast(digit as int); + accum = accum + cast(digit as int); } else { - accum -= cast(digit as int); + accum = accum - cast(digit as int); } // Detect overflow by comparing to last value, except @@ -556,15 +556,15 @@ pub fn from_str_bytes_common+ match char::to_digit(c, radix) { Some(digit) => { // Decrease power one order of magnitude - power /= radix_gen; + power = power / radix_gen; let digit_t: T = cast(digit); // add/subtract current digit depending on sign if accum_positive { - accum += digit_t * power; + accum = accum + digit_t * power; } else { - accum -= digit_t * power; + accum = accum - digit_t * power; } // Detect overflow by comparing to last value diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 400657d0c2559..4ef5d94349eb0 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -21,8 +21,8 @@ use cmp::Eq; use iterator::IteratorUtil; use libc; use option::{None, Option, Some}; -use str; use str::{Str, StrSlice, StrVector}; +use str; use to_str::ToStr; use ascii::{AsciiCast, AsciiStr}; use old_iter::BaseIter; @@ -440,7 +440,7 @@ impl ToStr for PosixPath { fn to_str(&self) -> ~str { let mut s = ~""; if self.is_absolute { - s += "/"; + s.push_str("/"); } s + self.components.connect("/") } @@ -619,15 +619,21 @@ impl ToStr for WindowsPath { fn to_str(&self) -> ~str { let mut s = ~""; match self.host { - Some(ref h) => { s += "\\\\"; s += *h; } + Some(ref h) => { + s.push_str("\\\\"); + s.push_str(*h); + } None => { } } match self.device { - Some(ref d) => { s += *d; s += ":"; } + Some(ref d) => { + s.push_str(*d); + s.push_str(":"); + } None => { } } if self.is_absolute { - s += "\\"; + s.push_str("\\"); } s + self.components.connect("\\") } diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 36100e3f52f99..f5444654758e5 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -261,8 +261,11 @@ fn highlight_lines(cm: @codemap::CodeMap, let s = fmt!("%s:%u ", fm.name, last_line + 1u); let mut indent = s.len(); let mut out = ~""; - while indent > 0u { out += " "; indent -= 1u; } - out += "...\n"; + while indent > 0u { + out.push_char(' '); + indent -= 1u; + } + out.push_str("...\n"); io::stderr().write_str(out); } @@ -283,22 +286,24 @@ fn highlight_lines(cm: @codemap::CodeMap, // part of the 'filename:line ' part of the previous line. let skip = fm.name.len() + digits + 3u; for skip.times() { - s += " "; + s.push_char(' '); } let orig = fm.get_line(lines.lines[0] as int); for uint::range(0u,left-skip) |pos| { let curChar = (orig[pos] as char); - s += match curChar { // Whenever a tab occurs on the previous - '\t' => "\t", // line, we insert one on the error-point- - _ => " " // -squigly-line as well (instead of a - }; // space). This way the squigly-line will - } // usually appear in the correct position. - s += "^"; + match curChar { // Whenever a tab occurs on the previous + '\t' => s.push_char('\t'), // line, we insert one on the error-point- + _ => s.push_char(' '), // -squigly-line as well (instead of a + } // space). This way the squigly-line will + } // usually appear in the correct position. + s.push_char('^'); let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { // the ^ already takes up one space let num_squiglies = hi.col.to_uint()-lo.col.to_uint()-1u; - for num_squiglies.times() { s += "~"; } + for num_squiglies.times() { + s.push_char('~') + } } io::stderr().write_str(s + "\n"); } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index bfb234106b8b1..5b3fa27b6531b 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -28,8 +28,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) } } else { match *e { - ast::tt_tok(_, token::IDENT(ident,_)) => - res_str += cx.str_of(ident), + ast::tt_tok(_, token::IDENT(ident,_)) => res_str.push_str(cx.str_of(ident)), _ => cx.span_fatal(sp, "concat_idents! requires ident args.") } } diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index b00f5057dac99..6269cafdd2960 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -68,8 +68,8 @@ impl gen_send for message { args_ast); let mut body = ~"{\n"; - body += fmt!("use super::%s;\n", name); - body += "let mut pipe = pipe;\n"; + body.push_str(fmt!("use super::%s;\n", name)); + body.push_str("let mut pipe = pipe;\n"); if this.proto.is_bounded() { let (sp, rp) = match (this.dir, next.dir) { @@ -79,13 +79,15 @@ impl gen_send for message { (recv, recv) => (~"c", ~"s") }; - body += "let mut b = pipe.reuse_buffer();\n"; - body += fmt!("let %s = ::std::pipes::SendPacketBuffered(\ - &mut (b.buffer.data.%s));\n", - sp, next.name); - body += fmt!("let %s = ::std::pipes::RecvPacketBuffered(\ - &mut (b.buffer.data.%s));\n", - rp, next.name); + body.push_str("let mut b = pipe.reuse_buffer();\n"); + body.push_str(fmt!("let %s = ::std::pipes::SendPacketBuffered(\ + &mut (b.buffer.data.%s));\n", + sp, + next.name)); + body.push_str(fmt!("let %s = ::std::pipes::RecvPacketBuffered(\ + &mut (b.buffer.data.%s));\n", + rp, + next.name)); } else { let pat = match (this.dir, next.dir) { @@ -95,23 +97,22 @@ impl gen_send for message { (recv, recv) => "(s, c)" }; - body += fmt!("let %s = ::std::pipes::entangle();\n", pat); + body.push_str(fmt!("let %s = ::std::pipes::entangle();\n", pat)); } - body += fmt!("let message = %s(%s);\n", - name, - vec::append_one( - arg_names.map(|x| cx.str_of(*x)), - @"s").connect(", ")); + body.push_str(fmt!("let message = %s(%s);\n", + name, + vec::append_one(arg_names.map(|x| cx.str_of(*x)), ~"s") + .connect(", "))); if !try { - body += fmt!("::std::pipes::send(pipe, message);\n"); + body.push_str(fmt!("::std::pipes::send(pipe, message);\n")); // return the new channel - body += "c }"; + body.push_str("c }"); } else { - body += fmt!("if ::std::pipes::send(pipe, message) {\n \ + body.push_str(fmt!("if ::std::pipes::send(pipe, message) {\n \ ::std::pipes::rt::make_some(c) \ - } else { ::std::pipes::rt::make_none() } }"); + } else { ::std::pipes::rt::make_none() } }")); } let body = cx.parse_expr(body.to_managed()); @@ -158,19 +159,19 @@ impl gen_send for message { }; let mut body = ~"{ "; - body += fmt!("use super::%s;\n", name); - body += fmt!("let message = %s%s;\n", name, message_args); + body.push_str(fmt!("use super::%s;\n", name)); + body.push_str(fmt!("let message = %s%s;\n", name, message_args)); if !try { - body += fmt!("::std::pipes::send(pipe, message);\n"); - body += " }"; + body.push_str(fmt!("::std::pipes::send(pipe, message);\n")); + body.push_str(" }"); } else { - body += fmt!("if ::std::pipes::send(pipe, message) \ + body.push_str(fmt!("if ::std::pipes::send(pipe, message) \ { \ ::std::pipes::rt::make_some(()) \ } else { \ ::std::pipes::rt::make_none() \ - } }"); + } }")); } let body = cx.parse_expr(body.to_managed()); @@ -435,10 +436,10 @@ impl gen_init for protocol { let mut server_states = ~[]; for (copy self.states).each |s| { - items += s.to_type_decls(cx); + items.push_all_move(s.to_type_decls(cx)); - client_states += s.to_endpoint_decls(cx, send); - server_states += s.to_endpoint_decls(cx, recv); + client_states.push_all_move(s.to_endpoint_decls(cx, send)); + server_states.push_all_move(s.to_endpoint_decls(cx, recv)); } if self.is_bounded() { diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index ddcad5c3e8f6c..d33b72ae3c90e 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -42,7 +42,7 @@ impl parser_attr for Parser { if self.look_ahead(1u) != token::LBRACKET { break; } - attrs += [self.parse_attribute(ast::attr_outer)]; + attrs.push(self.parse_attribute(ast::attr_outer)); } token::DOC_COMMENT(s) => { let attr = ::attr::mk_sugared_doc_attr( @@ -53,7 +53,7 @@ impl parser_attr for Parser { if attr.node.style != ast::attr_outer { self.fatal("expected outer comment"); } - attrs += [attr]; + attrs.push(attr); self.bump(); } _ => break @@ -77,9 +77,7 @@ impl parser_attr for Parser { self.expect(&token::RBRACKET); let hi = self.span.hi; return spanned(lo, hi, ast::attribute_ { style: style, - value: meta_item, - is_sugared_doc: false }); - } + value: meta_item, is_sugared_doc: false }); } // Parse attributes that appear after the opening of an item, each // terminated by a semicolon. In addition to a vector of inner attributes, @@ -105,7 +103,7 @@ impl parser_attr for Parser { let attr = self.parse_attribute(ast::attr_inner); if *self.token == token::SEMI { self.bump(); - inner_attrs += [attr]; + inner_attrs.push(attr); } else { // It's not really an inner attribute let outer_attr = @@ -113,7 +111,7 @@ impl parser_attr for Parser { ast::attribute_ { style: ast::attr_outer, value: attr.node.value, is_sugared_doc: false }); - next_outer_attrs += [outer_attr]; + next_outer_attrs.push(outer_attr); break; } } @@ -125,9 +123,9 @@ impl parser_attr for Parser { ); self.bump(); if attr.node.style == ast::attr_inner { - inner_attrs += [attr]; + inner_attrs.push(attr); } else { - next_outer_attrs += [attr]; + next_outer_attrs.push(attr); break; } } diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 5c56ea6c446c0..07ef4bd658698 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -241,7 +241,7 @@ fn read_block_comment(rdr: @mut StringReader, bump(rdr); } if !is_eof(rdr) { - curr_line += "*/"; + curr_line.push_str("*/"); bump(rdr); bump(rdr); } @@ -265,13 +265,13 @@ fn read_block_comment(rdr: @mut StringReader, if rdr.curr == '/' && nextch(rdr) == '*' { bump(rdr); bump(rdr); - curr_line += "*"; + curr_line.push_char('*'); level += 1; } else { if rdr.curr == '*' && nextch(rdr) == '/' { bump(rdr); bump(rdr); - curr_line += "/"; + curr_line.push_char('/'); level -= 1; } else { bump(rdr); } } diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 0956fa7225f20..708a77b7c1d40 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -194,10 +194,10 @@ impl Parser { ); } else { let mut s: ~str = ~"expected `"; - s += self.token_to_str(&token::GT); - s += "`, found `"; - s += self.this_token_to_str(); - s += "`"; + s.push_str(self.token_to_str(&token::GT)); + s.push_str("`, found `"); + s.push_str(self.this_token_to_str()); + s.push_str("`"); self.fatal(s); } } diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index d71e2763b5cda..39be08ce72a4c 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -183,7 +183,7 @@ pub fn bump(rdr: &mut StringReader) { let byte_offset_diff = next.next - current_byte_offset; rdr.pos = rdr.pos + BytePos(byte_offset_diff); rdr.curr = next.ch; - rdr.col += CharPos(1u); + rdr.col = rdr.col + CharPos(1u); if last_char == '\n' { rdr.filemap.next_line(rdr.last_pos); rdr.col = CharPos(0u); @@ -451,8 +451,8 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { is_float = true; bump(rdr); let dec_part = scan_digits(rdr, 10u); - num_str += "."; - num_str += dec_part; + num_str.push_char('.'); + num_str.push_str(dec_part); } if is_float { match base { @@ -464,7 +464,7 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { match scan_exponent(rdr) { Some(ref s) => { is_float = true; - num_str += (*s); + num_str.push_str(*s); } None => () } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 53d93ff8452f5..7c2ff4476d04a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4239,8 +4239,12 @@ impl Parser { // FAILURE TO PARSE ITEM if visibility != inherited { let mut s = ~"unmatched visibility `"; - s += if visibility == public { "pub" } else { "priv" }; - s += "`"; + if visibility == public { + s.push_str("pub") + } else { + s.push_str("priv") + } + s.push_char('`'); self.span_fatal(*self.last_span, s); } return iovi_none; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 7610175a37415..1fa1ccdf24e05 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -180,14 +180,14 @@ pub fn to_str(in: @ident_interner, t: &Token) -> ~str { LIT_FLOAT(ref s, t) => { let mut body = ident_to_str(s).to_owned(); if body.ends_with(".") { - body += "0"; // `10.f` is not a float literal + body.push_char('0'); // `10.f` is not a float literal } body + ast_util::float_ty_to_str(t) } LIT_FLOAT_UNSUFFIXED(ref s) => { let mut body = ident_to_str(s).to_owned(); if body.ends_with(".") { - body += "0"; // `10.f` is not a float literal + body.push_char('0'); // `10.f` is not a float literal } body } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 7853e7e312d41..03485b467f3af 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -124,12 +124,14 @@ pub fn buf_str(toks: ~[token], szs: ~[int], left: uint, right: uint, let mut s = ~"["; while i != right && L != 0u { L -= 1u; - if i != left { s += ", "; } - s += fmt!("%d=%s", szs[i], tok_str(toks[i])); + if i != left { + s.push_str(", "); + } + s.push_str(fmt!("%d=%s", szs[i], tok_str(toks[i]))); i += 1u; i %= n; } - s += "]"; + s.push_char(']'); return s; } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 287daf68effbe..b09a2c659ccab 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -87,9 +87,8 @@ fn vec_plus() { while i < 1500 { let rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); if r.gen() { - v += rv; - } - else { + v.push_all_move(rv); + } else { v = rv + v; } i += 1; diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs index 53b47b1214437..235295703e057 100644 --- a/src/test/bench/shootout-chameneos-redux.rs +++ b/src/test/bench/shootout-chameneos-redux.rs @@ -50,8 +50,8 @@ fn show_color(cc: color) -> ~str { fn show_color_list(set: ~[color]) -> ~str { let mut out = ~""; for vec::eachi(set) |_ii, col| { - out += " "; - out += show_color(*col); + out.push_char(' '); + out.push_str(show_color(*col)); } return out; } diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 5c77e698bec8b..58f4c1a38f54e 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -49,7 +49,7 @@ fn make_cumulative(aa: ~[AminoAcids]) -> ~[AminoAcids] { let mut ans: ~[AminoAcids] = ~[]; for aa.each |a| { cp += a.prob; - ans += [AminoAcids {ch: a.ch, prob: cp}]; + ans.push(AminoAcids {ch: a.ch, prob: cp}); } return ans; } diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index b7969fb0552e3..a6428944d6ccb 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -70,7 +70,7 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str { let b = str::raw::from_bytes(k); // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use // to_ascii_consume and to_str_consume to not do a unnecessary copy. - buffer += (fmt!("%s %0.3f\n", b.to_ascii().to_upper().to_str_ascii(), v)); + buffer.push_str(fmt!("%s %0.3f\n", b.to_ascii().to_upper().to_str_ascii(), v)); } } diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index d05edef25a6e2..fa92e97a18994 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -104,7 +104,9 @@ impl Sudoku { for u8::range(0u8, 9u8) |row| { for u8::range(0u8, 9u8) |col| { let color = self.grid[row][col]; - if color == 0u8 { work += [(row, col)]; } + if color == 0u8 { + work.push((row, col)); + } } } diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index cdc8d546dd848..8fecc64c2fee0 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -15,7 +15,7 @@ trait vec_monad { impl vec_monad for ~[A] { fn bind(&self, f: &fn(A) -> ~[B]) { let mut r = fail!(); - for self.each |elt| { r += f(*elt); } + for self.each |elt| { r = r + f(*elt); } //~^ WARNING unreachable expression //~^^ ERROR the type of this value must be known } diff --git a/src/test/run-fail/issue-3029.rs b/src/test/run-fail/issue-3029.rs index 6f4a3f5ab1d2e..caee00027883a 100644 --- a/src/test/run-fail/issue-3029.rs +++ b/src/test/run-fail/issue-3029.rs @@ -10,9 +10,9 @@ // error-pattern:so long fn main() { - let x = ~[]; + let mut x = ~[]; let y = ~[3]; fail!("so long"); - x += y; + x.push_all_move(y); ~"good" + ~"bye"; } diff --git a/src/test/run-pass/istr.rs b/src/test/run-pass/istr.rs index a82b263944982..ab89a357d349c 100644 --- a/src/test/run-pass/istr.rs +++ b/src/test/run-pass/istr.rs @@ -44,19 +44,19 @@ fn test_heap_add() { fn test_append() { let mut s = ~""; - s += ~"a"; + s.push_str(~"a"); assert_eq!(s, ~"a"); let mut s = ~"a"; - s += ~"b"; + s.push_str(~"b"); debug!(s.clone()); assert_eq!(s, ~"ab"); let mut s = ~"c"; - s += ~"offee"; + s.push_str(~"offee"); assert!(s == ~"coffee"); - s += ~"&tea"; + s.push_str(~"&tea"); assert!(s == ~"coffee&tea"); } diff --git a/src/test/run-pass/liveness-move-in-loop.rs b/src/test/run-pass/liveness-move-in-loop.rs index acdf388a8ff03..d910ac9a4e77a 100644 --- a/src/test/run-pass/liveness-move-in-loop.rs +++ b/src/test/run-pass/liveness-move-in-loop.rs @@ -15,7 +15,7 @@ fn the_loop() { loop { let x = 5; if x > 3 { - list += ~[take(x)]; + list.push(take(x)); } else { break; } diff --git a/src/test/run-pass/match-join.rs b/src/test/run-pass/match-join.rs index 66b6476806094..5ac62bae39224 100644 --- a/src/test/run-pass/match-join.rs +++ b/src/test/run-pass/match-join.rs @@ -23,7 +23,7 @@ fn foo(y: Option) { None:: => x = 17, _ => x = 42 } - rs += ~[x]; + rs.push(x); } return; } diff --git a/src/test/run-pass/monad.rs b/src/test/run-pass/monad.rs index 69545238db403..97caa6fbd093b 100644 --- a/src/test/run-pass/monad.rs +++ b/src/test/run-pass/monad.rs @@ -19,7 +19,9 @@ trait vec_monad { impl vec_monad for ~[A] { fn bind(&self, f: &fn(&A) -> ~[B]) -> ~[B] { let mut r = ~[]; - for self.each |elt| { r += f(elt); } + for self.each |elt| { + r.push_all_move(f(elt)); + } r } } diff --git a/src/test/run-pass/mutable-alias-vec.rs b/src/test/run-pass/mutable-alias-vec.rs index 1d9e7d3c64966..538aedcf7c887 100644 --- a/src/test/run-pass/mutable-alias-vec.rs +++ b/src/test/run-pass/mutable-alias-vec.rs @@ -13,7 +13,9 @@ extern mod extra; use std::vec; -fn grow(v: &mut ~[int]) { *v += ~[1]; } +fn grow(v: &mut ~[int]) { + v.push(1); +} pub fn main() { let mut v: ~[int] = ~[]; diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs index e75af5729d5c2..05aa1e7460839 100644 --- a/src/test/run-pass/operator-overloading.rs +++ b/src/test/run-pass/operator-overloading.rs @@ -57,7 +57,7 @@ impl cmp::Eq for Point { pub fn main() { let mut p = Point {x: 10, y: 20}; - p += Point {x: 101, y: 102}; + p = p + Point {x: 101, y: 102}; p = p - Point {x: 100, y: 100}; assert_eq!(p + Point {x: 5, y: 5}, Point {x: 16, y: 27}); assert_eq!(-p, Point {x: -11, y: -22}); diff --git a/src/test/run-pass/shadow.rs b/src/test/run-pass/shadow.rs index 99553cfcf79b4..a5b723cd4051f 100644 --- a/src/test/run-pass/shadow.rs +++ b/src/test/run-pass/shadow.rs @@ -19,7 +19,7 @@ fn foo(c: ~[int]) { for c.each |i| { debug!(a); let a = 17; - b += ~[a]; + b.push(a); } } _ => { } diff --git a/src/test/run-pass/static-impl.rs b/src/test/run-pass/static-impl.rs index 3d3f1404dc2a5..b6307bfa84c16 100644 --- a/src/test/run-pass/static-impl.rs +++ b/src/test/run-pass/static-impl.rs @@ -51,7 +51,9 @@ impl vec_utils for ~[T] { fn iter_(&self, f: &fn(&T)) { for self.each |x| { f(x); } } fn map_(&self, f: &fn(&T) -> U) -> ~[U] { let mut r = ~[]; - for self.each |elt| { r += ~[f(elt)]; } + for self.each |elt| { + r.push(f(elt)); + } r } } diff --git a/src/test/run-pass/str-append.rs b/src/test/run-pass/str-append.rs index 4fdf7dde031a7..556247eb4260e 100644 --- a/src/test/run-pass/str-append.rs +++ b/src/test/run-pass/str-append.rs @@ -15,7 +15,7 @@ extern mod extra; fn test1() { let mut s: ~str = ~"hello"; - s += ~"world"; + s.push_str("world"); debug!(s.clone()); assert_eq!(s[9], 'd' as u8); } diff --git a/src/test/run-pass/str-growth.rs b/src/test/run-pass/str-growth.rs index 6938b52eee83e..0cdf1841331a8 100644 --- a/src/test/run-pass/str-growth.rs +++ b/src/test/run-pass/str-growth.rs @@ -12,11 +12,11 @@ pub fn main() { let mut s = ~"a"; - s += ~"b"; + s.push_char('b'); assert_eq!(s[0], 'a' as u8); assert_eq!(s[1], 'b' as u8); - s += ~"c"; - s += ~"d"; + s.push_char('c'); + s.push_char('d'); assert_eq!(s[0], 'a' as u8); assert_eq!(s[1], 'b' as u8); assert_eq!(s[2], 'c' as u8); diff --git a/src/test/run-pass/trait-generic.rs b/src/test/run-pass/trait-generic.rs index 3aa30aab7c267..f6bb6c61544dc 100644 --- a/src/test/run-pass/trait-generic.rs +++ b/src/test/run-pass/trait-generic.rs @@ -31,7 +31,9 @@ trait map { impl map for ~[T] { fn map(&self, f: &fn(&T) -> U) -> ~[U] { let mut r = ~[]; - for self.each |x| { r += ~[f(x)]; } + for self.each |x| { + r.push(f(x)) + } r } } diff --git a/src/test/run-pass/vec-growth.rs b/src/test/run-pass/vec-growth.rs index 816228b62c674..c9a4c57cc9d36 100644 --- a/src/test/run-pass/vec-growth.rs +++ b/src/test/run-pass/vec-growth.rs @@ -12,10 +12,10 @@ pub fn main() { let mut v = ~[1]; - v += ~[2]; - v += ~[3]; - v += ~[4]; - v += ~[5]; + v.push(2); + v.push(3); + v.push(4); + v.push(5); assert_eq!(v[0], 1); assert_eq!(v[1], 2); assert_eq!(v[2], 3); diff --git a/src/test/run-pass/while-prelude-drop.rs b/src/test/run-pass/while-prelude-drop.rs index 082f2db259a4a..503e37fcd76ea 100644 --- a/src/test/run-pass/while-prelude-drop.rs +++ b/src/test/run-pass/while-prelude-drop.rs @@ -17,7 +17,7 @@ fn make(i: int) -> t { let mut s = ~"hello"; // Ensure s is non-const. - s += ~"there"; + s.push_str("there"); return b(s); } From ea861177a8472cdd92f2723e55a1041dbfaf5b8f Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 14 Jun 2013 18:21:47 -0700 Subject: [PATCH 11/13] librustc: Rewrite reachability and forbid duplicate methods in type implementations. This should allow fewer symbols to be exported. --- src/libextra/ebml.rs | 30 +- src/libextra/sync.rs | 12 +- src/libextra/test.rs | 248 ++++++------ src/librustc/driver/driver.rs | 16 +- src/librustc/metadata/encoder.rs | 79 ++-- src/librustc/metadata/tyencode.rs | 1 - src/librustc/middle/astencode.rs | 14 +- src/librustc/middle/mem_categorization.rs | 3 +- src/librustc/middle/reachable.rs | 414 ++++++++++++++++++++ src/librustc/middle/resolve.rs | 246 +++++------- src/librustc/middle/trans/base.rs | 31 +- src/librustc/middle/trans/callee.rs | 2 +- src/librustc/middle/trans/common.rs | 5 +- src/librustc/middle/trans/reachable.rs | 247 ------------ src/librustc/middle/typeck/check/mod.rs | 7 +- src/librustc/middle/typeck/collect.rs | 16 +- src/librustc/middle/typeck/infer/combine.rs | 3 +- src/librustc/middle/typeck/infer/lattice.rs | 116 ++++-- src/librustc/middle/typeck/infer/resolve.rs | 2 +- src/librustc/middle/typeck/infer/sub.rs | 1 + src/librustc/middle/typeck/infer/unify.rs | 95 +++-- src/librustc/rustc.rc | 2 +- src/librustpkg/rustpkg.rc | 15 +- src/libstd/path.rs | 56 ++- src/libstd/str.rs | 3 +- src/libsyntax/ast.rs | 5 +- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/parse/common.rs | 248 ------------ src/libsyntax/parse/obsolete.rs | 21 +- src/libsyntax/parse/parser.rs | 251 +++++++++++- 30 files changed, 1239 insertions(+), 952 deletions(-) create mode 100644 src/librustc/middle/reachable.rs delete mode 100644 src/librustc/middle/trans/reachable.rs diff --git a/src/libextra/ebml.rs b/src/libextra/ebml.rs index dd08f23a7a10f..797e00eda1f70 100644 --- a/src/libextra/ebml.rs +++ b/src/libextra/ebml.rs @@ -12,6 +12,8 @@ use core::prelude::*; +use core::str; + // Simple Extensible Binary Markup Language (ebml) reader and writer on a // cursor model. See the specification here: // http://www.matroska.org/technical/specs/rfc/index.html @@ -34,6 +36,20 @@ pub struct Doc { end: uint, } +impl Doc { + pub fn get(&self, tag: uint) -> Doc { + reader::get_doc(*self, tag) + } + + pub fn as_str_slice<'a>(&'a self) -> &'a str { + str::from_bytes_slice(self.data.slice(self.start, self.end)) + } + + pub fn as_str(&self) -> ~str { + self.as_str_slice().to_owned() + } +} + pub struct TaggedDoc { tag: uint, doc: Doc, @@ -89,20 +105,6 @@ pub mod reader { // ebml reading - impl Doc { - pub fn get(&self, tag: uint) -> Doc { - get_doc(*self, tag) - } - - pub fn as_str_slice<'a>(&'a self) -> &'a str { - str::from_bytes_slice(self.data.slice(self.start, self.end)) - } - - pub fn as_str(&self) -> ~str { - self.as_str_slice().to_owned() - } - } - struct Res { val: uint, next: uint diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs index 6d2932057f00a..a483cf182934e 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -151,7 +151,7 @@ impl Sem<()> { #[doc(hidden)] impl Sem<~[Waitqueue]> { - pub fn access(&self, blk: &fn() -> U) -> U { + pub fn access_waitqueue(&self, blk: &fn() -> U) -> U { let mut release = None; unsafe { do task::unkillable { @@ -352,7 +352,9 @@ fn check_cvar_bounds(out_of_bounds: Option, id: uint, act: &str, impl Sem<~[Waitqueue]> { // The only other place that condvars get built is rwlock_write_mode. pub fn access_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { - do self.access { blk(&Condvar { sem: self }) } + do self.access_waitqueue { + blk(&Condvar { sem: self }) + } } } @@ -425,7 +427,9 @@ impl Clone for Mutex { impl Mutex { /// Run a function with ownership of the mutex. - pub fn lock(&self, blk: &fn() -> U) -> U { (&self.sem).access(blk) } + pub fn lock(&self, blk: &fn() -> U) -> U { + (&self.sem).access_waitqueue(blk) + } /// Run a function with ownership of the mutex and a handle to a condvar. pub fn lock_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { @@ -519,7 +523,7 @@ impl RWlock { unsafe { do task::unkillable { (&self.order_lock).acquire(); - do (&self.access_lock).access { + do (&self.access_lock).access_waitqueue { (&self.order_lock).release(); task::rekillable(blk) } diff --git a/src/libextra/test.rs b/src/libextra/test.rs index 406dfb086eace..fbebcea10b498 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -19,16 +19,22 @@ use core::prelude::*; use getopts; use sort; +use stats::Stats; use term; +use time::precise_time_ns; use core::comm::{stream, SharedChan}; use core::either; use core::io; +use core::num; use core::option; +use core::rand::RngUtil; +use core::rand; use core::result; use core::str; use core::task; use core::to_str::ToStr; +use core::u64; use core::uint; use core::vec; @@ -610,152 +616,146 @@ fn calc_result(desc: &TestDesc, task_succeeded: bool) -> TestResult { } } -pub mod bench { - use core::prelude::*; - - use core::num; - use core::rand::RngUtil; - use core::rand; - use core::u64; - use core::vec; - use stats::Stats; - use test::{BenchHarness, BenchSamples}; - use time::precise_time_ns; - - impl BenchHarness { - /// Callback for benchmark functions to run in their body. - pub fn iter(&mut self, inner:&fn()) { - self.ns_start = precise_time_ns(); - let k = self.iterations; - for u64::range(0, k) |_| { - inner(); - } - self.ns_end = precise_time_ns(); +impl BenchHarness { + /// Callback for benchmark functions to run in their body. + pub fn iter(&mut self, inner:&fn()) { + self.ns_start = precise_time_ns(); + let k = self.iterations; + for u64::range(0, k) |_| { + inner(); } + self.ns_end = precise_time_ns(); + } - pub fn ns_elapsed(&mut self) -> u64 { - if self.ns_start == 0 || self.ns_end == 0 { - 0 - } else { - self.ns_end - self.ns_start - } + pub fn ns_elapsed(&mut self) -> u64 { + if self.ns_start == 0 || self.ns_end == 0 { + 0 + } else { + self.ns_end - self.ns_start } + } - pub fn ns_per_iter(&mut self) -> u64 { - if self.iterations == 0 { - 0 - } else { - self.ns_elapsed() / self.iterations - } + pub fn ns_per_iter(&mut self) -> u64 { + if self.iterations == 0 { + 0 + } else { + self.ns_elapsed() / self.iterations } + } - pub fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) { - self.iterations = n; - debug!("running benchmark for %u iterations", - n as uint); - f(self); - } + pub fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) { + self.iterations = n; + debug!("running benchmark for %u iterations", + n as uint); + f(self); + } - // This is the Go benchmark algorithm. It produces a single - // datapoint and always tries to run for 1s. - pub fn go_bench(&mut self, f: &fn(&mut BenchHarness)) { - - // Rounds a number down to the nearest power of 10. - fn round_down_10(n: u64) -> u64 { - let mut n = n; - let mut res = 1; - while n > 10 { - n = n / 10; - res *= 10; - } - res - } + // This is the Go benchmark algorithm. It produces a single + // datapoint and always tries to run for 1s. + pub fn go_bench(&mut self, f: &fn(&mut BenchHarness)) { - // Rounds x up to a number of the form [1eX, 2eX, 5eX]. - fn round_up(n: u64) -> u64 { - let base = round_down_10(n); - if n < (2 * base) { - 2 * base - } else if n < (5 * base) { - 5 * base - } else { - 10 * base - } + // Rounds a number down to the nearest power of 10. + fn round_down_10(n: u64) -> u64 { + let mut n = n; + let mut res = 1; + while n > 10 { + n = n / 10; + res *= 10; } + res + } - // Initial bench run to get ballpark figure. - let mut n = 1_u64; - self.bench_n(n, f); - - while n < 1_000_000_000 && - self.ns_elapsed() < 1_000_000_000 { - let last = n; - - // Try to estimate iter count for 1s falling back to 1bn - // iterations if first run took < 1ns. - if self.ns_per_iter() == 0 { - n = 1_000_000_000; - } else { - n = 1_000_000_000 / self.ns_per_iter(); - } - - n = u64::max(u64::min(n+n/2, 100*last), last+1); - n = round_up(n); - self.bench_n(n, f); + // Rounds x up to a number of the form [1eX, 2eX, 5eX]. + fn round_up(n: u64) -> u64 { + let base = round_down_10(n); + if n < (2 * base) { + 2 * base + } else if n < (5 * base) { + 5 * base + } else { + 10 * base } } - // This is a more statistics-driven benchmark algorithm. - // It stops as quickly as 50ms, so long as the statistical - // properties are satisfactory. If those properties are - // not met, it may run as long as the Go algorithm. - pub fn auto_bench(&mut self, f: &fn(&mut BenchHarness)) -> ~[f64] { - - let mut rng = rand::rng(); - let mut magnitude = 10; - let mut prev_madp = 0.0; + // Initial bench run to get ballpark figure. + let mut n = 1_u64; + self.bench_n(n, f); - loop { - let n_samples = rng.gen_uint_range(50, 60); - let n_iter = rng.gen_uint_range(magnitude, - magnitude * 2); + while n < 1_000_000_000 && + self.ns_elapsed() < 1_000_000_000 { + let last = n; - let samples = do vec::from_fn(n_samples) |_| { - self.bench_n(n_iter as u64, f); - self.ns_per_iter() as f64 - }; + // Try to estimate iter count for 1s falling back to 1bn + // iterations if first run took < 1ns. + if self.ns_per_iter() == 0 { + n = 1_000_000_000; + } else { + n = 1_000_000_000 / self.ns_per_iter(); + } - // Eliminate outliers - let med = samples.median(); - let mad = samples.median_abs_dev(); - let samples = do vec::filter(samples) |f| { - num::abs(*f - med) <= 3.0 * mad - }; + n = u64::max(u64::min(n+n/2, 100*last), last+1); + n = round_up(n); + self.bench_n(n, f); + } + } - debug!("%u samples, median %f, MAD=%f, %u survived filter", - n_samples, med as float, mad as float, - samples.len()); - - if samples.len() != 0 { - // If we have _any_ cluster of signal... - let curr_madp = samples.median_abs_dev_pct(); - if self.ns_elapsed() > 1_000_000 && - (curr_madp < 1.0 || - num::abs(curr_madp - prev_madp) < 0.1) { - return samples; - } - prev_madp = curr_madp; - - if n_iter > 20_000_000 || - self.ns_elapsed() > 20_000_000 { - return samples; - } + // This is a more statistics-driven benchmark algorithm. + // It stops as quickly as 50ms, so long as the statistical + // properties are satisfactory. If those properties are + // not met, it may run as long as the Go algorithm. + pub fn auto_bench(&mut self, f: &fn(&mut BenchHarness)) -> ~[f64] { + + let mut rng = rand::rng(); + let mut magnitude = 10; + let mut prev_madp = 0.0; + + loop { + let n_samples = rng.gen_uint_range(50, 60); + let n_iter = rng.gen_uint_range(magnitude, + magnitude * 2); + + let samples = do vec::from_fn(n_samples) |_| { + self.bench_n(n_iter as u64, f); + self.ns_per_iter() as f64 + }; + + // Eliminate outliers + let med = samples.median(); + let mad = samples.median_abs_dev(); + let samples = do vec::filter(samples) |f| { + num::abs(*f - med) <= 3.0 * mad + }; + + debug!("%u samples, median %f, MAD=%f, %u survived filter", + n_samples, med as float, mad as float, + samples.len()); + + if samples.len() != 0 { + // If we have _any_ cluster of signal... + let curr_madp = samples.median_abs_dev_pct(); + if self.ns_elapsed() > 1_000_000 && + (curr_madp < 1.0 || + num::abs(curr_madp - prev_madp) < 0.1) { + return samples; } + prev_madp = curr_madp; - magnitude *= 2; + if n_iter > 20_000_000 || + self.ns_elapsed() > 20_000_000 { + return samples; + } } + + magnitude *= 2; } } +} + +pub mod bench { + use core::prelude::*; + + use core::vec; + use test::{BenchHarness, BenchSamples}; pub fn benchmark(f: &fn(&mut BenchHarness)) -> BenchSamples { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index b72cdd40ecd5c..20d722fecd2bb 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -19,7 +19,7 @@ use front; use lib::llvm::llvm; use metadata::{creader, cstore, filesearch}; use metadata; -use middle::{trans, freevars, kind, ty, typeck, lint, astencode}; +use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable}; use middle; use util::common::time; use util::ppaux; @@ -304,6 +304,10 @@ pub fn compile_rest(sess: Session, time(time_passes, ~"kind checking", || kind::check_crate(ty_cx, method_map, crate)); + let reachable_map = + time(time_passes, ~"reachability checking", || + reachable::find_reachable(ty_cx, method_map, crate)); + time(time_passes, ~"lint checking", || lint::check_crate(ty_cx, crate)); @@ -315,14 +319,18 @@ pub fn compile_rest(sess: Session, vtable_map: vtable_map, write_guard_map: write_guard_map, moves_map: moves_map, - capture_map: capture_map + capture_map: capture_map, }; let outputs = outputs.get_ref(); time(time_passes, ~"translation", || - trans::base::trans_crate(sess, crate, ty_cx, + trans::base::trans_crate(sess, + crate, + ty_cx, &outputs.obj_filename, - exp_map2, maps)) + exp_map2, + reachable_map, + maps)) }; let outputs = outputs.get_ref(); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 2518bf95a97e6..c3f86930a002f 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -16,7 +16,6 @@ use metadata::common::*; use metadata::cstore; use metadata::decoder; use metadata::tyencode; -use middle::trans::reachable; use middle::ty::node_id_to_type; use middle::ty; use middle; @@ -59,7 +58,6 @@ pub type encode_inlined_item = @fn(ecx: @EncodeContext, pub struct EncodeParams { diag: @span_handler, tcx: ty::ctxt, - reachable: reachable::map, reexports2: middle::resolve::ExportMap2, item_symbols: @mut HashMap, discrim_symbols: @mut HashMap, @@ -86,7 +84,6 @@ pub struct EncodeContext { diag: @span_handler, tcx: ty::ctxt, stats: @mut Stats, - reachable: reachable::map, reexports2: middle::resolve::ExportMap2, item_symbols: @mut HashMap, discrim_symbols: @mut HashMap, @@ -96,10 +93,6 @@ pub struct EncodeContext { type_abbrevs: abbrev_map } -pub fn reachable(ecx: @EncodeContext, id: node_id) -> bool { - ecx.reachable.contains(&id) -} - fn encode_name(ecx: @EncodeContext, ebml_w: &mut writer::Encoder, name: ident) { @@ -155,8 +148,8 @@ fn encode_trait_ref(ebml_w: &mut writer::Encoder, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs) + }; ebml_w.start_tag(tag); tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref); @@ -182,8 +175,8 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs) + }; for params.each |param| { ebml_w.start_tag(tag); tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param); @@ -214,8 +207,8 @@ pub fn write_type(ecx: @EncodeContext, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs) + }; tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ); } @@ -226,8 +219,8 @@ pub fn write_vstore(ecx: @EncodeContext, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs) + }; tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore); } @@ -258,8 +251,8 @@ fn encode_method_fty(ecx: @EncodeContext, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs) + }; tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ); ebml_w.end_tag(); @@ -776,13 +769,6 @@ fn encode_info_for_item(ecx: @EncodeContext, index: @mut ~[entry], path: &[ast_map::path_elt]) { let tcx = ecx.tcx; - let must_write = - match item.node { - item_enum(_, _) | item_impl(*) | item_trait(*) | item_struct(*) | - item_mod(*) | item_foreign_mod(*) | item_const(*) => true, - _ => false - }; - if !must_write && !reachable(ecx, item.id) { return; } fn add_to_index_(item: @item, ebml_w: &writer::Encoder, index: @mut ~[entry]) { @@ -890,23 +876,6 @@ fn encode_info_for_item(ecx: @EncodeContext, encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); - // If this is a tuple- or enum-like struct, encode the type of the - // constructor. - if struct_def.fields.len() > 0 && - struct_def.fields[0].node.kind == ast::unnamed_field { - let ctor_id = match struct_def.ctor_id { - Some(ctor_id) => ctor_id, - None => ecx.tcx.sess.bug("struct def didn't have ctor id"), - }; - - encode_info_for_struct_ctor(ecx, - ebml_w, - path, - item.ident, - ctor_id, - index); - } - encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); @@ -936,6 +905,23 @@ fn encode_info_for_item(ecx: @EncodeContext, let bkts = create_index(idx); encode_index(ebml_w, bkts, write_int); ebml_w.end_tag(); + + // If this is a tuple- or enum-like struct, encode the type of the + // constructor. + if struct_def.fields.len() > 0 && + struct_def.fields[0].node.kind == ast::unnamed_field { + let ctor_id = match struct_def.ctor_id { + Some(ctor_id) => ctor_id, + None => ecx.tcx.sess.bug("struct def didn't have ctor id"), + }; + + encode_info_for_struct_ctor(ecx, + ebml_w, + path, + item.ident, + ctor_id, + index); + } } item_impl(ref generics, opt_trait, ty, ref methods) => { add_to_index(); @@ -1082,7 +1068,6 @@ fn encode_info_for_foreign_item(ecx: @EncodeContext, index: @mut ~[entry], path: ast_map::path, abi: AbiSet) { - if !reachable(ecx, nitem.id) { return; } index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() }); ebml_w.start_tag(tag_items_data_item); @@ -1141,6 +1126,12 @@ fn encode_info_for_items(ecx: @EncodeContext, visit::visit_foreign_item(ni, (cx, v)); match ecx.tcx.items.get_copy(&ni.id) { ast_map::node_foreign_item(_, abi, _, pt) => { + debug!("writing foreign item %s::%s", + ast_map::path_to_str( + *pt, + token::get_ident_interner()), + *token::ident_to_str(&ni.ident)); + let mut ebml_w = copy ebml_w; encode_info_for_foreign_item(ecx, &mut ebml_w, @@ -1442,14 +1433,13 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { total_bytes: 0, n_inlines: 0 }; - let EncodeParams{item_symbols, diag, tcx, reachable, reexports2, + let EncodeParams{item_symbols, diag, tcx, reexports2, discrim_symbols, cstore, encode_inlined_item, link_meta, _} = parms; let ecx = @EncodeContext { diag: diag, tcx: tcx, stats: @mut stats, - reachable: reachable, reexports2: reexports2, item_symbols: item_symbols, discrim_symbols: discrim_symbols, @@ -1531,7 +1521,6 @@ pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str { diag: tcx.diag, ds: def_to_str, tcx: tcx, - reachable: |_id| false, abbrevs: tyencode::ac_no_abbrevs}; do io::with_str_writer |wr| { tyencode::enc_ty(wr, cx, t); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index d233021121411..4d54ac76119a4 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -31,7 +31,6 @@ pub struct ctxt { ds: @fn(def_id) -> ~str, // The type context. tcx: ty::ctxt, - reachable: @fn(node_id) -> bool, abbrevs: abbrev_ctxt } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 209ab4ce3d4cb..9c03aafed9731 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -380,6 +380,9 @@ impl tr for ast::def { did2_opt.map(|did2| did2.tr(xcx)), p) } + ast::def_method(did0, did1) => { + ast::def_method(did0.tr(xcx), did1.map(|did1| did1.tr(xcx))) + } ast::def_self_ty(nid) => { ast::def_self_ty(xcx.tr_id(nid)) } ast::def_self(nid, i) => { ast::def_self(xcx.tr_id(nid), i) } ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) } @@ -709,11 +712,12 @@ trait get_ty_str_ctxt { impl get_ty_str_ctxt for e::EncodeContext { // IMPLICIT SELF WARNING: fix this! fn ty_str_ctxt(@self) -> @tyencode::ctxt { - @tyencode::ctxt {diag: self.tcx.sess.diagnostic(), - ds: e::def_to_str, - tcx: self.tcx, - reachable: |a| encoder::reachable(self, a), - abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)} + @tyencode::ctxt { + diag: self.tcx.sess.diagnostic(), + ds: e::def_to_str, + tcx: self.tcx, + abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs) + } } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3152b66440ce9..5786667dc17e0 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -453,7 +453,8 @@ impl mem_categorization_ctxt { ast::def_trait(_) | ast::def_ty(_) | ast::def_prim_ty(_) | ast::def_ty_param(*) | ast::def_struct(*) | ast::def_typaram_binder(*) | ast::def_region(_) | - ast::def_label(_) | ast::def_self_ty(*) => { + ast::def_label(_) | ast::def_self_ty(*) | + ast::def_method(*) => { @cmt_ { id:id, span:span, diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs new file mode 100644 index 0000000000000..1361f2c245afc --- /dev/null +++ b/src/librustc/middle/reachable.rs @@ -0,0 +1,414 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Finds items that are externally reachable, to determine which items +// need to have their metadata (and possibly their AST) serialized. +// All items that can be referred to through an exported name are +// reachable, and when a reachable thing is inline or generic, it +// makes all other generics or inline functions that it references +// reachable as well. + +use core::prelude::*; +use core::iterator::IteratorUtil; + +use middle::resolve; +use middle::ty; +use middle::typeck; + +use core::hashmap::HashSet; +use syntax::ast::*; +use syntax::ast; +use syntax::ast_map; +use syntax::ast_util::def_id_of_def; +use syntax::attr; +use syntax::codemap; +use syntax::parse::token; +use syntax::visit::Visitor; +use syntax::visit; + +// Returns true if the given set of attributes contains the `#[inline]` +// attribute. +fn attributes_specify_inlining(attrs: &[attribute]) -> bool { + attr::attrs_contains_name(attrs, "inline") +} + +// Returns true if the given set of generics implies that the item it's +// associated with must be inlined. +fn generics_require_inlining(generics: &Generics) -> bool { + !generics.ty_params.is_empty() +} + +// Returns true if the given item must be inlined because it may be +// monomorphized or it was marked with `#[inline]`. This will only return +// true for functions. +fn item_might_be_inlined(item: @item) -> bool { + if attributes_specify_inlining(item.attrs) { + return true + } + + match item.node { + item_fn(_, _, _, ref generics, _) => { + generics_require_inlining(generics) + } + _ => false, + } +} + +// Returns true if the given type method must be inlined because it may be +// monomorphized or it was marked with `#[inline]`. +fn ty_method_might_be_inlined(ty_method: &ty_method) -> bool { + attributes_specify_inlining(ty_method.attrs) || + generics_require_inlining(&ty_method.generics) +} + +// Returns true if the given trait method must be inlined because it may be +// monomorphized or it was marked with `#[inline]`. +fn trait_method_might_be_inlined(trait_method: &trait_method) -> bool { + match *trait_method { + required(ref ty_method) => ty_method_might_be_inlined(ty_method), + provided(_) => true + } +} + +// Information needed while computing reachability. +struct ReachableContext { + // The type context. + tcx: ty::ctxt, + // The method map, which links node IDs of method call expressions to the + // methods they've been resolved to. + method_map: typeck::method_map, + // The set of items which must be exported in the linkage sense. + reachable_symbols: @mut HashSet, + // A worklist of item IDs. Each item ID in this worklist will be inlined + // and will be scanned for further references. + worklist: @mut ~[node_id], +} + +impl ReachableContext { + // Creates a new reachability computation context. + fn new(tcx: ty::ctxt, method_map: typeck::method_map) + -> ReachableContext { + ReachableContext { + tcx: tcx, + method_map: method_map, + reachable_symbols: @mut HashSet::new(), + worklist: @mut ~[], + } + } + + // Step 1: Mark all public symbols, and add all public symbols that might + // be inlined to a worklist. + fn mark_public_symbols(&self, crate: @crate) { + let reachable_symbols = self.reachable_symbols; + let worklist = self.worklist; + let visitor = visit::mk_vt(@Visitor { + visit_item: |item, _, visitor| { + match item.node { + item_fn(*) => { + reachable_symbols.insert(item.id); + if item_might_be_inlined(item) { + worklist.push(item.id) + } + } + item_struct(ref struct_def, _) => { + match struct_def.ctor_id { + None => {} + Some(ctor_id) => { + reachable_symbols.insert(ctor_id); + } + } + } + item_enum(ref enum_def, _) => { + for enum_def.variants.each |variant| { + reachable_symbols.insert(variant.node.id); + } + } + item_impl(ref generics, trait_ref, _, ref methods) => { + // XXX(pcwalton): We conservatively assume any methods + // on a trait implementation are reachable, when this + // is not the case. We could be more precise by only + // treating implementations of reachable or cross- + // crate traits as reachable. + + // Mark all public methods as reachable. + for methods.each |method| { + if method.vis == public || trait_ref.is_some() { + reachable_symbols.insert(method.id); + } + } + + if generics_require_inlining(generics) { + // If the impl itself has generics, add all public + // symbols to the worklist. + for methods.each |method| { + if method.vis == public || + trait_ref.is_some() { + worklist.push(method.id) + } + } + } else { + // Otherwise, add only public methods that have + // generics to the worklist. + for methods.each |method| { + let generics = &method.generics; + let attrs = &method.attrs; + if generics_require_inlining(generics) || + attributes_specify_inlining(*attrs) || + method.vis == public || + trait_ref.is_some() { + worklist.push(method.id) + } + } + } + } + item_trait(_, _, ref trait_methods) => { + // Mark all provided methods as reachable. + for trait_methods.each |trait_method| { + match *trait_method { + provided(method) => { + reachable_symbols.insert(method.id); + worklist.push(method.id) + } + required(_) => {} + } + } + } + _ => {} + } + + if item.vis == public { + visit::visit_item(item, (), visitor) + } + }, + .. *visit::default_visitor() + }); + + visit::visit_crate(crate, (), visitor) + } + + // Returns true if the given def ID represents a local item that is + // eligible for inlining and false otherwise. + fn def_id_represents_local_inlined_item(tcx: ty::ctxt, def_id: def_id) + -> bool { + if def_id.crate != local_crate { + return false + } + + let node_id = def_id.node; + match tcx.items.find(&node_id) { + Some(&ast_map::node_item(item, _)) => { + match item.node { + item_fn(*) => item_might_be_inlined(item), + _ => false, + } + } + Some(&ast_map::node_trait_method(trait_method, _, _)) => { + match *trait_method { + required(_) => false, + provided(_) => true, + } + } + Some(&ast_map::node_method(method, impl_did, _)) => { + if generics_require_inlining(&method.generics) || + attributes_specify_inlining(method.attrs) { + true + } else { + // Check the impl. If the generics on the self type of the + // impl require inlining, this method does too. + assert!(impl_did.crate == local_crate); + match tcx.items.find(&impl_did.node) { + Some(&ast_map::node_item(item, _)) => { + match item.node { + item_impl(ref generics, _, _, _) => { + generics_require_inlining(generics) + } + _ => false + } + } + Some(_) => { + tcx.sess.span_bug(method.span, + "method is not inside an \ + impl?!") + } + None => { + tcx.sess.span_bug(method.span, + "the impl that this method is \ + supposedly inside of doesn't \ + exist in the AST map?!") + } + } + } + } + Some(_) => false, + None => tcx.sess.bug("def ID not in def map?!"), + } + } + + // Helper function to set up a visitor for `propagate()` below. + fn init_visitor(&self) -> visit::vt<()> { + let (worklist, method_map) = (self.worklist, self.method_map); + let (tcx, reachable_symbols) = (self.tcx, self.reachable_symbols); + visit::mk_vt(@visit::Visitor { + visit_expr: |expr, _, visitor| { + match expr.node { + expr_path(_) => { + let def = match tcx.def_map.find(&expr.id) { + Some(&def) => def, + None => { + tcx.sess.span_bug(expr.span, + "def ID not in def map?!") + } + }; + + let def_id = def_id_of_def(def); + if ReachableContext:: + def_id_represents_local_inlined_item(tcx, + def_id) { + worklist.push(def_id.node) + } + reachable_symbols.insert(def_id.node); + } + expr_method_call(*) => { + match method_map.find(&expr.id) { + Some(&typeck::method_map_entry { + origin: typeck::method_static(def_id), + _ + }) => { + if ReachableContext:: + def_id_represents_local_inlined_item( + tcx, + def_id) { + worklist.push(def_id.node) + } + reachable_symbols.insert(def_id.node); + } + Some(_) => {} + None => { + tcx.sess.span_bug(expr.span, + "method call expression \ + not in method map?!") + } + } + } + _ => {} + } + + visit::visit_expr(expr, (), visitor) + }, + ..*visit::default_visitor() + }) + } + + // Step 2: Mark all symbols that the symbols on the worklist touch. + fn propagate(&self) { + let visitor = self.init_visitor(); + let mut scanned = HashSet::new(); + while self.worklist.len() > 0 { + let search_item = self.worklist.pop(); + if scanned.contains(&search_item) { + loop + } + scanned.insert(search_item); + self.reachable_symbols.insert(search_item); + + // Find the AST block corresponding to the item and visit it, + // marking all path expressions that resolve to something + // interesting. + match self.tcx.items.find(&search_item) { + Some(&ast_map::node_item(item, _)) => { + match item.node { + item_fn(_, _, _, _, ref search_block) => { + visit::visit_block(search_block, (), visitor) + } + _ => { + self.tcx.sess.span_bug(item.span, + "found non-function item \ + in worklist?!") + } + } + } + Some(&ast_map::node_trait_method(trait_method, _, _)) => { + match *trait_method { + required(ref ty_method) => { + self.tcx.sess.span_bug(ty_method.span, + "found required method in \ + worklist?!") + } + provided(ref method) => { + visit::visit_block(&method.body, (), visitor) + } + } + } + Some(&ast_map::node_method(ref method, _, _)) => { + visit::visit_block(&method.body, (), visitor) + } + Some(_) => { + let ident_interner = token::get_ident_interner(); + let desc = ast_map::node_id_to_str(self.tcx.items, + search_item, + ident_interner); + self.tcx.sess.bug(fmt!("found unexpected thingy in \ + worklist: %s", + desc)) + } + None => { + self.tcx.sess.bug(fmt!("found unmapped ID in worklist: \ + %d", + search_item)) + } + } + } + } + + // Step 3: Mark all destructors as reachable. + // + // XXX(pcwalton): This is a conservative overapproximation, but fixing + // this properly would result in the necessity of computing *type* + // reachability, which might result in a compile time loss. + fn mark_destructors_reachable(&self) { + for self.tcx.destructor_for_type.each |_, destructor_def_id| { + if destructor_def_id.crate == local_crate { + self.reachable_symbols.insert(destructor_def_id.node); + } + } + } +} + +pub fn find_reachable(tcx: ty::ctxt, + method_map: typeck::method_map, + crate: @crate) + -> @mut HashSet { + // XXX(pcwalton): We only need to mark symbols that are exported. But this + // is more complicated than just looking at whether the symbol is `pub`, + // because it might be the target of a `pub use` somewhere. For now, I + // think we are fine, because you can't `pub use` something that wasn't + // exported due to the bug whereby `use` only looks through public + // modules even if you're inside the module the `use` appears in. When + // this bug is fixed, however, this code will need to be updated. Probably + // the easiest way to fix this (although a conservative overapproximation) + // is to have the name resolution pass mark all targets of a `pub use` as + // "must be reachable". + + let reachable_context = ReachableContext::new(tcx, method_map); + + // Step 1: Mark all public symbols, and add all public symbols that might + // be inlined to a worklist. + reachable_context.mark_public_symbols(crate); + + // Step 2: Mark all symbols that the symbols on the worklist touch. + reachable_context.propagate(); + + // Step 3: Mark all destructors as reachable. + reachable_context.mark_destructors_reachable(); + + // Return the set of reachable symbols. + reachable_context.reachable_symbols +} + diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 89f2053c8a583..584daadd305c1 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -645,21 +645,9 @@ impl NameBindings { match self.type_def { None => None, Some(ref type_def) => { - // FIXME (#3784): This is reallllly questionable. - // Perhaps the right thing to do is to merge def_mod - // and def_ty. match (*type_def).type_def { Some(type_def) => Some(type_def), - None => { - match (*type_def).module_def { - Some(module_def) => { - let module_def = &mut *module_def; - module_def.def_id.map(|def_id| - def_mod(*def_id)) - } - None => None - } - } + None => None, } } } @@ -1216,49 +1204,29 @@ impl Resolver { visit_item(item, (new_parent, visitor)); } - item_impl(_, trait_ref_opt, ty, ref methods) => { - // If this implements an anonymous trait and it has static - // methods, then add all the static methods within to a new - // module, if the type was defined within this module. + item_impl(_, None, ty, ref methods) => { + // If this implements an anonymous trait, then add all the + // methods within to a new module, if the type was defined + // within this module. // // FIXME (#3785): This is quite unsatisfactory. Perhaps we // should modify anonymous traits to only be implementable in // the same module that declared the type. - // Bail out early if there are no static methods. - let mut methods_seen = HashMap::new(); - let mut has_static_methods = false; - for methods.each |method| { - match method.explicit_self.node { - sty_static => has_static_methods = true, - _ => { - // Make sure you can't define duplicate methods - let ident = method.ident; - let span = method.span; - let old_sp = methods_seen.find_or_insert(ident, span); - if *old_sp != span { - self.session.span_err(span, - fmt!("duplicate definition of method `%s`", - self.session.str_of(ident))); - self.session.span_note(*old_sp, - fmt!("first definition of method `%s` here", - self.session.str_of(ident))); - } - } - } - } - - // If there are static methods, then create the module - // and add them. - match (trait_ref_opt, ty) { - (None, @Ty { node: ty_path(path, _), _ }) if - has_static_methods && path.idents.len() == 1 => { + // Create the module and add all methods. + match *ty { + Ty { + node: ty_path(path, _), + _ + } if path.idents.len() == 1 => { let name = path_to_ident(path); let new_parent = match parent.children.find(&name) { // It already exists - Some(&child) if child.get_module_if_available().is_some() && - child.get_module().kind == ImplModuleKind => { + Some(&child) if child.get_module_if_available() + .is_some() && + child.get_module().kind == + ImplModuleKind => { ModuleReducedGraphParent(child.get_module()) } // Create the module @@ -1269,8 +1237,8 @@ impl Resolver { ForbidDuplicateModules, sp); - let parent_link = self.get_parent_link(new_parent, - ident); + let parent_link = + self.get_parent_link(new_parent, ident); let def_id = local_def(item.id); name_bindings.define_module(Public, parent_link, @@ -1278,30 +1246,36 @@ impl Resolver { ImplModuleKind, sp); - ModuleReducedGraphParent(name_bindings.get_module()) + ModuleReducedGraphParent( + name_bindings.get_module()) } }; - // For each static method... + // For each method... for methods.each |method| { - match method.explicit_self.node { + // Add the method to the module. + let ident = method.ident; + let (method_name_bindings, _) = + self.add_child(ident, + new_parent, + ForbidDuplicateValues, + method.span); + let def = match method.explicit_self.node { sty_static => { - // Add the static method to the - // module. - let ident = method.ident; - let (method_name_bindings, _) = - self.add_child( - ident, - new_parent, - ForbidDuplicateValues, - method.span); - let def = def_fn(local_def(method.id), - method.purity); - method_name_bindings.define_value( - Public, def, method.span); + // Static methods become `def_fn`s. + def_fn(local_def(method.id), + method.purity) } - _ => {} - } + _ => { + // Non-static methods become + // `def_method`s. + def_method(local_def(method.id), None) + } + }; + + method_name_bindings.define_value(Public, + def, + method.span); } } _ => {} @@ -1310,41 +1284,23 @@ impl Resolver { visit_item(item, (parent, visitor)); } + item_impl(_, Some(_), ty, ref methods) => { + visit_item(item, parent, visitor); + } + item_trait(_, _, ref methods) => { let (name_bindings, new_parent) = self.add_child(ident, parent, ForbidDuplicateTypes, sp); - // If the trait has static methods, then add all the static - // methods within to a new module. - // - // We only need to create the module if the trait has static - // methods, so check that first. - let mut has_static_methods = false; - for (*methods).each |method| { - let ty_m = trait_method_to_ty_method(method); - match ty_m.explicit_self.node { - sty_static => { - has_static_methods = true; - break; - } - _ => {} - } - } - - // Create the module if necessary. - let module_parent_opt; - if has_static_methods { - let parent_link = self.get_parent_link(parent, ident); - name_bindings.define_module(privacy, - parent_link, - Some(local_def(item.id)), - TraitModuleKind, - sp); - module_parent_opt = Some(ModuleReducedGraphParent( - name_bindings.get_module())); - } else { - module_parent_opt = None; - } + // Add all the methods within to a new module. + let parent_link = self.get_parent_link(parent, ident); + name_bindings.define_module(privacy, + parent_link, + Some(local_def(item.id)), + TraitModuleKind, + sp); + let module_parent = ModuleReducedGraphParent(name_bindings. + get_module()); // Add the names of all the methods to the trait info. let mut method_names = HashMap::new(); @@ -1352,35 +1308,34 @@ impl Resolver { let ty_m = trait_method_to_ty_method(method); let ident = ty_m.ident; - // Add it to the trait info if not static, - // add it as a name in the trait module otherwise. - match ty_m.explicit_self.node { - sty_static => { - let def = def_static_method( - local_def(ty_m.id), - Some(local_def(item.id)), - ty_m.purity); - let (method_name_bindings, _) = - self.add_child(ident, - module_parent_opt.get(), - ForbidDuplicateValues, - ty_m.span); - method_name_bindings.define_value(Public, - def, - ty_m.span); + // Add it as a name in the trait module. + let def = match ty_m.explicit_self.node { + sty_static => { + // Static methods become `def_static_method`s. + def_static_method(local_def(ty_m.id), + Some(local_def(item.id)), + ty_m.purity) } _ => { - // Make sure you can't define duplicate methods - let old_sp = method_names.find_or_insert(ident, ty_m.span); - if *old_sp != ty_m.span { - self.session.span_err(ty_m.span, - fmt!("duplicate definition of method `%s`", - self.session.str_of(ident))); - self.session.span_note(*old_sp, - fmt!("first definition of method `%s` here", - self.session.str_of(ident))); - } + // Non-static methods become `def_method`s. + def_method(local_def(ty_m.id), + Some(local_def(item.id))) + } + }; + + let (method_name_bindings, _) = + self.add_child(ident, + module_parent, + ForbidDuplicateValues, + ty_m.span); + method_name_bindings.define_value(Public, def, ty_m.span); + + // Add it to the trait info if not static. + match ty_m.explicit_self.node { + sty_static => {} + _ => { + method_names.insert(ident); } } } @@ -1735,6 +1690,9 @@ impl Resolver { child_name_bindings.define_type(privacy, def, dummy_sp()); self.structs.insert(def_id); } + def_method(*) => { + // Ignored; handled elsewhere. + } def_self(*) | def_arg(*) | def_local(*) | def_prim_ty(*) | def_ty_param(*) | def_binding(*) | def_use(*) | def_upvar(*) | def_region(*) | @@ -2376,7 +2334,8 @@ impl Resolver { } match type_result { BoundResult(target_module, name_bindings) => { - debug!("(resolving single import) found type target"); + debug!("(resolving single import) found type target: %?", + name_bindings.type_def.get().type_def); import_resolution.type_target = Some(Target(target_module, name_bindings)); import_resolution.type_id = directive.id; @@ -3254,21 +3213,6 @@ impl Resolver { pub fn add_exports_for_module(@mut self, exports2: &mut ~[Export2], module_: @mut Module) { - for module_.children.each |ident, namebindings| { - debug!("(computing exports) maybe export '%s'", - self.session.str_of(*ident)); - self.add_exports_of_namebindings(&mut *exports2, - *ident, - *namebindings, - TypeNS, - false); - self.add_exports_of_namebindings(&mut *exports2, - *ident, - *namebindings, - ValueNS, - false); - } - for module_.import_resolutions.each |ident, importresolution| { if importresolution.privacy != Public { debug!("(computing exports) not reexporting private `%s`", @@ -4494,8 +4438,8 @@ impl Resolver { if path.global { return self.resolve_crate_relative_path(path, - self.xray_context, - namespace); + self.xray_context, + namespace); } if path.idents.len() > 1 { @@ -4924,6 +4868,22 @@ impl Resolver { // Write the result into the def map. debug!("(resolving expr) resolved `%s`", self.idents_to_str(path.idents)); + + // First-class methods are not supported yet; error + // out here. + match def { + def_method(*) => { + self.session.span_err(expr.span, + "first-class methods \ + are not supported"); + self.session.span_note(expr.span, + "call the method \ + using the `.` \ + syntax"); + } + _ => {} + } + self.record_def(expr.id, def); } None => { @@ -5392,7 +5352,7 @@ pub fn resolve_crate(session: Session, -> CrateMap { let resolver = @mut Resolver(session, lang_items, crate); resolver.resolve(); - let Resolver{def_map, export_map2, trait_map, _} = copy *resolver; + let Resolver { def_map, export_map2, trait_map, _ } = copy *resolver; CrateMap { def_map: def_map, exp_map2: export_map2, diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 60725fa6b7346..9872470366b1d 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -55,7 +55,6 @@ use middle::trans::machine; use middle::trans::machine::{llalign_of_min, llsize_of}; use middle::trans::meth; use middle::trans::monomorphize; -use middle::trans::reachable; use middle::trans::shape::*; use middle::trans::tvec; use middle::trans::type_of; @@ -203,11 +202,11 @@ pub fn get_extern_const(externs: ExternMap, llmod: ModuleRef, } } - fn get_simple_extern_fn(cx: block, - externs: ExternMap, - llmod: ModuleRef, - name: @str, - n_args: int) -> ValueRef { +fn get_simple_extern_fn(cx: block, + externs: ExternMap, + llmod: ModuleRef, + name: @str, + n_args: int) -> ValueRef { let _icx = cx.insn_ctxt("get_simple_extern_fn"); let ccx = cx.fcx.ccx; let inputs = vec::from_elem(n_args as uint, ccx.int_type); @@ -2433,7 +2432,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { match ccx.item_vals.find(&id) { Some(&v) => v, None => { - let mut exprt = false; + let mut exprt = ccx.reachable_map.contains(&id); let val = match tcx.items.get_copy(&id) { ast_map::node_item(i, pth) => { let my_path = vec::append(/*bad*/copy *pth, @@ -2485,7 +2484,6 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { } } ast_map::node_method(m, _, pth) => { - exprt = true; register_method(ccx, id, pth, m) } ast_map::node_foreign_item(ni, _, _, pth) => { @@ -2560,7 +2558,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { variant)) } }; - if !(exprt || ccx.reachable.contains(&id)) { + if !exprt { lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); } ccx.item_vals.insert(id, val); @@ -2968,7 +2966,6 @@ pub fn crate_ctxt_to_encode_parms(cx: @CrateContext) encoder::EncodeParams { diag: cx.sess.diagnostic(), tcx: cx.tcx, - reachable: cx.reachable, reexports2: cx.exp_map2, item_symbols: cx.item_symbols, discrim_symbols: cx.discrim_symbols, @@ -3016,16 +3013,12 @@ pub fn trans_crate(sess: session::Session, tcx: ty::ctxt, output: &Path, emap2: resolve::ExportMap2, - maps: astencode::Maps) -> (ModuleRef, LinkMeta) { + reachable_map: @mut HashSet, + maps: astencode::Maps) + -> (ContextRef, ModuleRef, LinkMeta) { let symbol_hasher = @mut hash::default_state(); let link_meta = link::build_link_meta(sess, crate, output, symbol_hasher); - let reachable = reachable::find_reachable( - &crate.node.module, - emap2, - tcx, - maps.method_map - ); // Append ".rc" to crate name as LLVM module identifier. // @@ -3077,7 +3070,6 @@ pub fn trans_crate(sess: session::Session, intrinsics: intrinsics, item_vals: @mut HashMap::new(), exp_map2: emap2, - reachable: reachable, item_symbols: @mut HashMap::new(), link_meta: link_meta, enum_sizes: @mut HashMap::new(), @@ -3129,7 +3121,8 @@ pub fn trans_crate(sess: session::Session, crate_map: crate_map, uses_gc: @mut false, dbg_cx: dbg_cx, - do_not_commit_warning_issued: @mut false + do_not_commit_warning_issued: @mut false, + reachable_map: reachable_map, }; { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index e2373a809e76c..dfe07f214d3e4 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -144,7 +144,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee { ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) | ast::def_use(*) | ast::def_typaram_binder(*) | ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) | - ast::def_self_ty(*) => { + ast::def_self_ty(*) | ast::def_method(*) => { bcx.tcx().sess.span_bug( ref_expr.span, fmt!("Cannot translate def %? \ diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 0d411e7341b4d..dfc3e05a10563 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -29,7 +29,6 @@ use middle::trans::build; use middle::trans::datum; use middle::trans::debuginfo; use middle::trans::glue; -use middle::trans::reachable; use middle::trans::shape; use middle::trans::type_of; use middle::trans::type_use; @@ -167,7 +166,6 @@ pub struct CrateContext { intrinsics: HashMap<&'static str, ValueRef>, item_vals: @mut HashMap, exp_map2: resolve::ExportMap2, - reachable: reachable::map, item_symbols: @mut HashMap, link_meta: LinkMeta, enum_sizes: @mut HashMap, @@ -231,7 +229,8 @@ pub struct CrateContext { // is not emitted by LLVM's GC pass when no functions use GC. uses_gc: @mut bool, dbg_cx: Option, - do_not_commit_warning_issued: @mut bool + do_not_commit_warning_issued: @mut bool, + reachable_map: @mut HashSet, } // Types used for llself. diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs deleted file mode 100644 index d30409ffb919f..0000000000000 --- a/src/librustc/middle/trans/reachable.rs +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Finds items that are externally reachable, to determine which items -// need to have their metadata (and possibly their AST) serialized. -// All items that can be referred to through an exported name are -// reachable, and when a reachable thing is inline or generic, it -// makes all other generics or inline functions that it references -// reachable as well. - -use core::prelude::*; -use core::iterator::IteratorUtil; - -use middle::resolve; -use middle::ty; -use middle::typeck; - -use core::hashmap::HashSet; -use syntax::ast; -use syntax::ast::*; -use syntax::ast_util::def_id_of_def; -use syntax::attr; -use syntax::codemap; -use syntax::print::pprust::expr_to_str; -use syntax::{visit, ast_map}; - -pub type map = @HashSet; - -struct ctx<'self> { - exp_map2: resolve::ExportMap2, - tcx: ty::ctxt, - method_map: typeck::method_map, - rmap: &'self mut HashSet, -} - -pub fn find_reachable(crate_mod: &_mod, exp_map2: resolve::ExportMap2, - tcx: ty::ctxt, method_map: typeck::method_map) -> map { - let mut rmap = HashSet::new(); - { - let cx = @mut ctx { - exp_map2: exp_map2, - tcx: tcx, - method_map: method_map, - rmap: &mut rmap - }; - traverse_public_mod(cx, ast::crate_node_id, crate_mod); - traverse_all_resources_and_impls(cx, crate_mod); - } - return @rmap; -} - -fn traverse_exports(cx: @mut ctx, mod_id: node_id) -> bool { - let mut found_export = false; - match cx.exp_map2.find(&mod_id) { - Some(ref exp2s) => { - for (*exp2s).each |e2| { - found_export = true; - traverse_def_id(cx, e2.def_id) - }; - } - None => () - } - return found_export; -} - -fn traverse_def_id(cx: @mut ctx, did: def_id) { - if did.crate != local_crate { return; } - match cx.tcx.items.find(&did.node) { - None => (), // This can happen for self, for example - Some(&ast_map::node_item(item, _)) => traverse_public_item(cx, item), - Some(&ast_map::node_method(_, impl_id, _)) => traverse_def_id(cx, impl_id), - Some(&ast_map::node_foreign_item(item, _, _, _)) => { - let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut - cx.rmap.insert(item.id); - } - Some(&ast_map::node_variant(ref v, _, _)) => { - let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut - cx.rmap.insert(v.node.id); - } - _ => () - } -} - -fn traverse_public_mod(cx: @mut ctx, mod_id: node_id, m: &_mod) { - if !traverse_exports(cx, mod_id) { - // No exports, so every local item is exported - for m.items.each |item| { - traverse_public_item(cx, *item); - } - } -} - -fn traverse_public_item(cx: @mut ctx, item: @item) { - { - // FIXME #6021: naming rmap shouldn't be necessary - let cx = &mut *cx; - let rmap: &mut HashSet = cx.rmap; - if rmap.contains(&item.id) { return; } - rmap.insert(item.id); - } - - match item.node { - item_mod(ref m) => traverse_public_mod(cx, item.id, m), - item_foreign_mod(ref nm) => { - if !traverse_exports(cx, item.id) { - for nm.items.each |item| { - let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut - cx.rmap.insert(item.id); - } - } - } - item_fn(_, _, _, ref generics, ref blk) => { - if generics.ty_params.len() > 0u || - attr::find_inline_attr(item.attrs) != attr::ia_none { - traverse_inline_body(cx, blk); - } - } - item_impl(ref generics, _, _, ref ms) => { - for ms.each |m| { - if generics.ty_params.len() > 0u || - m.generics.ty_params.len() > 0u || - attr::find_inline_attr(m.attrs) != attr::ia_none - { - { - let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut - cx.rmap.insert(m.id); - } - traverse_inline_body(cx, &m.body); - } - } - } - item_struct(ref struct_def, _) => { - for struct_def.ctor_id.iter().advance |&ctor_id| { - let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut - cx.rmap.insert(ctor_id); - } - } - item_ty(t, _) => { - traverse_ty(t, (cx, - visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty, - ..*visit::default_visitor()}))) - } - item_const(*) | - item_enum(*) | item_trait(*) => (), - item_mac(*) => fail!("item macros unimplemented") - } -} - -fn traverse_ty<'a>(ty: @Ty, (cx, v): (@mut ctx<'a>, visit::vt<@mut ctx<'a>>)) { - { - let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut - if cx.rmap.contains(&ty.id) { return; } - cx.rmap.insert(ty.id); - } - - match ty.node { - ty_path(p, p_id) => { - match cx.tcx.def_map.find(&p_id) { - // Kind of a hack to check this here, but I'm not sure what else - // to do - Some(&def_prim_ty(_)) => { /* do nothing */ } - Some(&d) => traverse_def_id(cx, def_id_of_def(d)), - None => { /* do nothing -- but should we fail here? */ } - } - for p.types.each |t| { - (v.visit_ty)(*t, (cx, v)); - } - } - _ => visit::visit_ty(ty, (cx, v)) - } -} - -fn traverse_inline_body(cx: @mut ctx, body: &blk) { - fn traverse_expr<'a>(e: @expr, (cx, v): (@mut ctx<'a>, - visit::vt<@mut ctx<'a>>)) { - match e.node { - expr_path(_) => { - match cx.tcx.def_map.find(&e.id) { - Some(&d) => { - traverse_def_id(cx, def_id_of_def(d)); - } - None => cx.tcx.sess.span_bug( - e.span, - fmt!("Unbound node id %? while traversing %s", - e.id, - expr_to_str(e, cx.tcx.sess.intr()))) - } - } - expr_method_call(*) => { - match cx.method_map.find(&e.id) { - Some(&typeck::method_map_entry { - origin: typeck::method_static(did), - _ - }) => { - traverse_def_id(cx, did); - } - Some(_) => {} - None => { - cx.tcx.sess.span_bug(e.span, "expr_method_call not in \ - method map"); - } - } - } - _ => () - } - visit::visit_expr(e, (cx, v)); - } - // Don't ignore nested items: for example if a generic fn contains a - // generic impl (as in deque::create), we need to monomorphize the - // impl as well - fn traverse_item(i: @item, (cx, _v): (@mut ctx, visit::vt<@mut ctx>)) { - traverse_public_item(cx, i); - } - visit::visit_block(body, (cx, visit::mk_vt(@visit::Visitor { - visit_expr: traverse_expr, - visit_item: traverse_item, - ..*visit::default_visitor() - }))); -} - -fn traverse_all_resources_and_impls(cx: @mut ctx, crate_mod: &_mod) { - visit::visit_mod( - crate_mod, - codemap::dummy_sp(), - 0, - (cx, - visit::mk_vt(@visit::Visitor { - visit_expr: |_e, (_cx, _v)| { }, - visit_item: |i, (cx, v)| { - visit::visit_item(i, (cx, v)); - match i.node { - item_impl(*) => { - traverse_public_item(cx, i); - } - _ => () - } - }, - ..*visit::default_visitor() - }))); -} diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index c018cc6b8ac45..baa45a20ee05d 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -792,10 +792,6 @@ impl FnCtxt { ast_ty_to_ty(self, self, ast_t) } - pub fn expr_to_str(&self, expr: @ast::expr) -> ~str { - expr.repr(self.tcx()) - } - pub fn pat_to_str(&self, pat: @ast::pat) -> ~str { pat.repr(self.tcx()) } @@ -3293,6 +3289,9 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, ast::def_self_ty(*) => { fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty"); } + ast::def_method(*) => { + fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method"); + } } } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 1e2333dab5611..29909a99aac99 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -121,10 +121,20 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) { }))); } -impl CrateCtxt { +pub trait ToTy { fn to_ty( - &self, rs: &RS, ast_ty: @ast::Ty) -> ty::t - { + &self, + rs: &RS, + ast_ty: @ast::Ty) + -> ty::t; +} + +impl ToTy for CrateCtxt { + fn to_ty( + &self, + rs: &RS, + ast_ty: @ast::Ty) + -> ty::t { ast_ty_to_ty(self, rs, ast_ty) } } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 7668167489209..d25fc727ef911 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -64,7 +64,8 @@ use middle::typeck::infer::glb::Glb; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::sub::Sub; use middle::typeck::infer::to_str::InferStr; -use middle::typeck::infer::{cres, InferCtxt, ures}; +use middle::typeck::infer::unify::{InferCtxtMethods, UnifyInferCtxtMethods}; +use middle::typeck::infer::{InferCtxt, cres, ures}; use util::common::indent; use core::result::{iter_vec2, map_vec2}; diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index 820bb2f86b04c..9e94a270b0db7 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -71,15 +71,53 @@ impl LatticeValue for ty::t { } } -impl CombineFields { - pub fn var_sub_var>>(&self, - a_id: - V, - b_id: - V) - -> - ures { +pub trait CombineFieldsLatticeMethods { + fn var_sub_var>>(&self, + a_id: V, + b_id: V) + -> ures; + /// make variable a subtype of T + fn var_sub_t>>( + &self, + a_id: V, + b: T) + -> ures; + fn t_sub_var>>( + &self, + a: T, + b_id: V) + -> ures; + fn merge_bnd( + &self, + a: &Bound, + b: &Bound, + lattice_op: LatticeOp) + -> cres>; + fn set_var_to_merged_bounds>>( + &self, + v_id: V, + a: &Bounds, + b: &Bounds, + rank: uint) + -> ures; + fn bnds( + &self, + a: &Bound, + b: &Bound) + -> ures; +} + +impl CombineFieldsLatticeMethods for CombineFields { + fn var_sub_var>>( + &self, + a_id: V, + b_id: V) + -> ures { /*! * * Make one variable a subtype of another variable. This is a @@ -127,12 +165,12 @@ impl CombineFields { } /// make variable a subtype of T - pub fn var_sub_t>>(&self, - a_id: V, - b: T) - -> ures - { + fn var_sub_t>>( + &self, + a_id: V, + b: T) + -> ures { /*! * * Make a variable (`a_id`) a subtype of the concrete type `b` */ @@ -151,12 +189,12 @@ impl CombineFields { a_id, a_bounds, b_bounds, node_a.rank) } - pub fn t_sub_var>>(&self, - a: T, - b_id: V) - -> ures - { + fn t_sub_var>>( + &self, + a: T, + b_id: V) + -> ures { /*! * * Make a concrete type (`a`) a subtype of the variable `b_id` */ @@ -175,12 +213,12 @@ impl CombineFields { b_id, a_bounds, b_bounds, node_b.rank) } - pub fn merge_bnd(&self, - a: &Bound, - b: &Bound, - lattice_op: - LatticeOp) - -> cres> { + fn merge_bnd( + &self, + a: &Bound, + b: &Bound, + lattice_op: LatticeOp) + -> cres> { /*! * * Combines two bounds into a more general bound. */ @@ -202,14 +240,14 @@ impl CombineFields { } } - pub fn set_var_to_merged_bounds>>( - &self, - v_id: V, - a: &Bounds, - b: &Bounds, - rank: uint) - -> ures { + fn set_var_to_merged_bounds>>( + &self, + v_id: V, + a: &Bounds, + b: &Bounds, + rank: uint) + -> ures { /*! * * Updates the bounds for the variable `v_id` to be the intersection @@ -264,10 +302,10 @@ impl CombineFields { uok() } - pub fn bnds(&self, - a: &Bound, - b: &Bound) - -> ures { + fn bnds(&self, + a: &Bound, + b: &Bound) + -> ures { debug!("bnds(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx)); let _r = indenter(); diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs index ab52ef36978a5..1311907eed2ee 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -54,7 +54,7 @@ use middle::ty; use middle::typeck::infer::{Bounds, cyclic_ty, fixup_err, fres, InferCtxt}; use middle::typeck::infer::{region_var_bound_by_region_var, unresolved_ty}; use middle::typeck::infer::to_str::InferStr; -use middle::typeck::infer::unify::Root; +use middle::typeck::infer::unify::{Root, UnifyInferCtxtMethods}; use util::common::{indent, indenter}; use util::ppaux::ty_to_str; diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 2578f7c855359..38740a2922b37 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -18,6 +18,7 @@ use middle::typeck::infer::combine::*; use middle::typeck::infer::cres; use middle::typeck::infer::glb::Glb; use middle::typeck::infer::InferCtxt; +use middle::typeck::infer::lattice::CombineFieldsLatticeMethods; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::to_str::InferStr; use util::common::{indent, indenter}; diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index c6e4b485d29b5..c86ecfa10b632 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -40,9 +40,31 @@ pub trait UnifyVid { -> &'v mut ValsAndBindings; } -impl InferCtxt { - pub fn get>(&mut self, vid: V) - -> Node { +pub trait UnifyInferCtxtMethods { + fn get>( + &mut self, + vid: V) + -> Node; + fn set>( + &mut self, + vid: V, + new_v: VarValue); + fn unify>( + &mut self, + node_a: &Node, + node_b: &Node) + -> (V, uint); +} + +impl UnifyInferCtxtMethods for InferCtxt { + fn get>( + &mut self, + vid: V) + -> Node { /*! * * Find the root node for `vid`. This uses the standard @@ -84,10 +106,11 @@ impl InferCtxt { } } - pub fn set>(&mut self, - vid: V, - new_v: VarValue) { + fn set>( + &mut self, + vid: V, + new_v: VarValue) { /*! * * Sets the value for `vid` to `new_v`. `vid` MUST be a root node! @@ -104,11 +127,12 @@ impl InferCtxt { } } - pub fn unify>(&mut self, - node_a: &Node, - node_b: &Node) - -> (V, uint) { + fn unify>( + &mut self, + node_a: &Node, + node_b: &Node) + -> (V, uint) { // Rank optimization: if you don't know what it is, check // out @@ -157,14 +181,31 @@ pub fn mk_err(a_is_expected: bool, } } -impl InferCtxt { - pub fn simple_vars>>(&mut self, - a_is_expected: - bool, - a_id: V, - b_id: V) - -> ures { +pub trait InferCtxtMethods { + fn simple_vars>>( + &mut self, + a_is_expected: bool, + a_id: V, + b_id: V) + -> ures; + fn simple_var_t>>( + &mut self, + a_is_expected: bool, + a_id: V, + b: T) + -> ures; +} + +impl InferCtxtMethods for InferCtxt { + fn simple_vars>>( + &mut self, + a_is_expected: bool, + a_id: V, + b_id: V) + -> ures { /*! * * Unifies two simple variables. Because simple variables do @@ -196,13 +237,13 @@ impl InferCtxt { return uok(); } - pub fn simple_var_t>>(&mut self, - a_is_expected - : bool, - a_id: V, - b: T) - -> ures { + fn simple_var_t>>( + &mut self, + a_is_expected: bool, + a_id: V, + b: T) + -> ures { /*! * * Sets the value of the variable `a_id` to `b`. Because diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 7d86b312908c7..f89edcb02acb8 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -91,7 +91,6 @@ pub mod middle { pub mod shape; pub mod debuginfo; pub mod type_use; - pub mod reachable; pub mod machine; pub mod adt; pub mod asm; @@ -121,6 +120,7 @@ pub mod middle { pub mod moves; pub mod entry; pub mod effect; + pub mod reachable; } pub mod front { diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index f9dc9a6160f90..4614fc123c2df 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -179,7 +179,20 @@ impl<'self> PkgScript<'self> { } -impl Ctx { +pub trait CtxMethods { + fn run(&self, cmd: &str, args: ~[~str]); + fn do_cmd(&self, _cmd: &str, _pkgname: &str); + fn build(&self, workspace: &Path, pkgid: &PkgId); + fn clean(&self, workspace: &Path, id: &PkgId); + fn info(&self); + fn install(&self, workspace: &Path, id: &PkgId); + fn prefer(&self, _id: &str, _vers: Option<~str>); + fn test(&self); + fn uninstall(&self, _id: &str, _vers: Option<~str>); + fn unprefer(&self, _id: &str, _vers: Option<~str>); +} + +impl CtxMethods for Ctx { fn run(&self, cmd: &str, args: ~[~str]) { match cmd { diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 4ef5d94349eb0..7363e51d23beb 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -308,8 +308,8 @@ mod stat { } } - -impl Path { +#[cfg(target_os = "win32")] +impl WindowsPath { pub fn stat(&self) -> Option { unsafe { do str::as_c_str(self.to_str()) |buf| { @@ -322,12 +322,35 @@ impl Path { } } - #[cfg(unix)] - pub fn lstat(&self) -> Option { + pub fn exists(&self) -> bool { + match self.stat() { + None => false, + Some(_) => true, + } + } + + pub fn get_size(&self) -> Option { + match self.stat() { + None => None, + Some(ref st) => Some(st.st_size as i64), + } + } + + pub fn get_mode(&self) -> Option { + match self.stat() { + None => None, + Some(ref st) => Some(st.st_mode as uint), + } + } +} + +#[cfg(not(target_os = "win32"))] +impl PosixPath { + pub fn stat(&self) -> Option { unsafe { - do str::as_c_str(self.to_str()) |buf| { + do str::as_c_str(self.to_str()) |buf| { let mut st = stat::arch::default_stat(); - match libc::lstat(buf, &mut st) { + match libc::stat(buf, &mut st) { 0 => Some(st), _ => None, } @@ -360,7 +383,7 @@ impl Path { #[cfg(target_os = "freebsd")] #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] -impl Path { +impl PosixPath { pub fn get_atime(&self) -> Option<(i64, int)> { match self.stat() { None => None, @@ -392,9 +415,24 @@ impl Path { } } +#[cfg(unix)] +impl PosixPath { + pub fn lstat(&self) -> Option { + unsafe { + do str::as_c_str(self.to_str()) |buf| { + let mut st = stat::arch::default_stat(); + match libc::lstat(buf, &mut st) { + 0 => Some(st), + _ => None, + } + } + } + } +} + #[cfg(target_os = "freebsd")] #[cfg(target_os = "macos")] -impl Path { +impl PosixPath { pub fn get_birthtime(&self) -> Option<(i64, int)> { match self.stat() { None => None, @@ -407,7 +445,7 @@ impl Path { } #[cfg(target_os = "win32")] -impl Path { +impl WindowsPath { pub fn get_atime(&self) -> Option<(i64, int)> { match self.stat() { None => None, diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 0c630ea4fe150..de680e61c3976 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1156,7 +1156,8 @@ pub mod raw { /// invalidated later. pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str { let s = s as *u8; - let mut (curr, len) = (s, 0u); + let mut curr = s; + let mut len = 0u; while *curr != 0u8 { len += 1u; curr = ptr::offset(s, len); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7b7e9a3852db3..748df6b212f19 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -207,7 +207,8 @@ pub enum def { def_struct(def_id), def_typaram_binder(node_id), /* struct, impl or trait with ty params */ def_region(node_id), - def_label(node_id) + def_label(node_id), + def_method(def_id /* method */, Option /* trait */), } @@ -1047,7 +1048,7 @@ pub struct trait_ref { pub enum visibility { public, private, inherited } impl visibility { - fn inherit_from(&self, parent_visibility: visibility) -> visibility { + pub fn inherit_from(&self, parent_visibility: visibility) -> visibility { match self { &inherited => parent_visibility, &public | &private => *self diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index e2d1b037d3bf5..615fa955d8e47 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -62,7 +62,7 @@ pub fn def_id_of_def(d: def) -> def_id { def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | - def_use(id) | def_struct(id) | def_trait(id) => { + def_use(id) | def_struct(id) | def_trait(id) | def_method(id, _) => { id } def_arg(id, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id) diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 708a77b7c1d40..9c6637381516d 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -53,251 +53,3 @@ pub fn token_to_str(token: &token::Token) -> ~str { token::to_str(get_ident_interner(), token) } -impl Parser { - // convert a token to a string using self's reader - pub fn token_to_str(&self, token: &token::Token) -> ~str { - token::to_str(get_ident_interner(), token) - } - - // convert the current token to a string using self's reader - pub fn this_token_to_str(&self) -> ~str { - self.token_to_str(self.token) - } - - pub fn unexpected_last(&self, t: &token::Token) -> ! { - self.span_fatal( - *self.last_span, - fmt!( - "unexpected token: `%s`", - self.token_to_str(t) - ) - ); - } - - pub fn unexpected(&self) -> ! { - self.fatal( - fmt!( - "unexpected token: `%s`", - self.this_token_to_str() - ) - ); - } - - // expect and consume the token t. Signal an error if - // the next token is not t. - pub fn expect(&self, t: &token::Token) { - if *self.token == *t { - self.bump(); - } else { - self.fatal( - fmt!( - "expected `%s` but found `%s`", - self.token_to_str(t), - self.this_token_to_str() - ) - ) - } - } - - pub fn parse_ident(&self) -> ast::ident { - self.check_strict_keywords(); - self.check_reserved_keywords(); - match *self.token { - token::IDENT(i, _) => { - self.bump(); - i - } - token::INTERPOLATED(token::nt_ident(*)) => { - self.bug("ident interpolation not converted to real token"); - } - _ => { - self.fatal( - fmt!( - "expected ident, found `%s`", - self.this_token_to_str() - ) - ); - } - } - } - - pub fn parse_path_list_ident(&self) -> ast::path_list_ident { - let lo = self.span.lo; - let ident = self.parse_ident(); - let hi = self.last_span.hi; - spanned(lo, hi, ast::path_list_ident_ { name: ident, - id: self.get_id() }) - } - - // consume token 'tok' if it exists. Returns true if the given - // token was present, false otherwise. - pub fn eat(&self, tok: &token::Token) -> bool { - return if *self.token == *tok { self.bump(); true } else { false }; - } - - pub fn is_keyword(&self, kw: keywords::Keyword) -> bool { - token::is_keyword(kw, self.token) - } - - // if the next token is the given keyword, eat it and return - // true. Otherwise, return false. - pub fn eat_keyword(&self, kw: keywords::Keyword) -> bool { - let is_kw = match *self.token { - token::IDENT(sid, false) => kw.to_ident().name == sid.name, - _ => false - }; - if is_kw { self.bump() } - is_kw - } - - // if the given word is not a keyword, signal an error. - // if the next token is not the given word, signal an error. - // otherwise, eat it. - pub fn expect_keyword(&self, kw: keywords::Keyword) { - if !self.eat_keyword(kw) { - self.fatal( - fmt!( - "expected `%s`, found `%s`", - self.id_to_str(kw.to_ident()), - self.this_token_to_str() - ) - ); - } - } - - // signal an error if the given string is a strict keyword - pub fn check_strict_keywords(&self) { - if token::is_strict_keyword(self.token) { - self.span_err(*self.last_span, - fmt!("found `%s` in ident position", self.this_token_to_str())); - } - } - - // signal an error if the current token is a reserved keyword - pub fn check_reserved_keywords(&self) { - if token::is_reserved_keyword(self.token) { - self.fatal(fmt!("`%s` is a reserved keyword", self.this_token_to_str())); - } - } - - // expect and consume a GT. if a >> is seen, replace it - // with a single > and continue. If a GT is not seen, - // signal an error. - pub fn expect_gt(&self) { - if *self.token == token::GT { - self.bump(); - } else if *self.token == token::BINOP(token::SHR) { - self.replace_token( - token::GT, - self.span.lo + BytePos(1u), - self.span.hi - ); - } else { - let mut s: ~str = ~"expected `"; - s.push_str(self.token_to_str(&token::GT)); - s.push_str("`, found `"); - s.push_str(self.this_token_to_str()); - s.push_str("`"); - self.fatal(s); - } - } - - // parse a sequence bracketed by '<' and '>', stopping - // before the '>'. - pub fn parse_seq_to_before_gt(&self, - sep: Option, - f: &fn(&Parser) -> T) - -> OptVec { - let mut first = true; - let mut v = opt_vec::Empty; - while *self.token != token::GT - && *self.token != token::BINOP(token::SHR) { - match sep { - Some(ref t) => { - if first { first = false; } - else { self.expect(t); } - } - _ => () - } - v.push(f(self)); - } - return v; - } - - pub fn parse_seq_to_gt(&self, - sep: Option, - f: &fn(&Parser) -> T) - -> OptVec { - let v = self.parse_seq_to_before_gt(sep, f); - self.expect_gt(); - return v; - } - - // parse a sequence, including the closing delimiter. The function - // f must consume tokens until reaching the next separator or - // closing bracket. - pub fn parse_seq_to_end(&self, - ket: &token::Token, - sep: SeqSep, - f: &fn(&Parser) -> T) - -> ~[T] { - let val = self.parse_seq_to_before_end(ket, sep, f); - self.bump(); - val - } - - // parse a sequence, not including the closing delimiter. The function - // f must consume tokens until reaching the next separator or - // closing bracket. - pub fn parse_seq_to_before_end(&self, - ket: &token::Token, - sep: SeqSep, - f: &fn(&Parser) -> T) - -> ~[T] { - let mut first: bool = true; - let mut v: ~[T] = ~[]; - while *self.token != *ket { - match sep.sep { - Some(ref t) => { - if first { first = false; } - else { self.expect(t); } - } - _ => () - } - if sep.trailing_sep_allowed && *self.token == *ket { break; } - v.push(f(self)); - } - return v; - } - - // parse a sequence, including the closing delimiter. The function - // f must consume tokens until reaching the next separator or - // closing bracket. - pub fn parse_unspanned_seq(&self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: &fn(&Parser) -> T) - -> ~[T] { - self.expect(bra); - let result = self.parse_seq_to_before_end(ket, sep, f); - self.bump(); - result - } - - // NB: Do not use this function unless you actually plan to place the - // spanned list in the AST. - pub fn parse_seq(&self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: &fn(&Parser) -> T) - -> spanned<~[T]> { - let lo = self.span.lo; - self.expect(bra); - let result = self.parse_seq_to_before_end(ket, sep, f); - let hi = self.span.hi; - self.bump(); - spanned(lo, hi, result) - } -} diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 155d33792c01c..b9833d5f707f0 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -76,7 +76,26 @@ impl to_bytes::IterBytes for ObsoleteSyntax { } } -impl Parser { +pub trait ParserObsoleteMethods { + /// Reports an obsolete syntax non-fatal error. + fn obsolete(&self, sp: span, kind: ObsoleteSyntax); + // Reports an obsolete syntax non-fatal error, and returns + // a placeholder expression + fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr; + fn report(&self, + sp: span, + kind: ObsoleteSyntax, + kind_str: &str, + desc: &str); + fn token_is_obsolete_ident(&self, ident: &str, token: &Token) -> bool; + fn is_obsolete_ident(&self, ident: &str) -> bool; + fn eat_obsolete_ident(&self, ident: &str) -> bool; + fn try_parse_obsolete_struct_ctor(&self) -> bool; + fn try_parse_obsolete_with(&self) -> bool; + fn try_parse_obsolete_priv_section(&self, attrs: &[attribute]) -> bool; +} + +impl ParserObsoleteMethods for Parser { /// Reports an obsolete syntax non-fatal error. pub fn obsolete(&self, sp: span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7c2ff4476d04a..d5ebc6635be02 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -66,7 +66,7 @@ use codemap::{span, BytePos, spanned, mk_sp}; use codemap; use parse::attr::parser_attr; use parse::classify; -use parse::common::{seq_sep_none}; +use parse::common::{SeqSep, seq_sep_none}; use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed}; use parse::lexer::reader; use parse::lexer::TokenAndSpan; @@ -86,7 +86,7 @@ use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod}; use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType}; use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl}; use parse::obsolete::{ObsoleteMutWithMultipleBindings}; -use parse::obsolete::{ObsoletePatternCopyKeyword}; +use parse::obsolete::{ObsoletePatternCopyKeyword, ParserObsoleteMethods}; use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident}; use parse::token::{is_ident_or_path}; use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents}; @@ -277,6 +277,253 @@ impl Drop for Parser { } impl Parser { + // convert a token to a string using self's reader + pub fn token_to_str(&self, token: &token::Token) -> ~str { + token::to_str(get_ident_interner(), token) + } + + // convert the current token to a string using self's reader + pub fn this_token_to_str(&self) -> ~str { + self.token_to_str(self.token) + } + + pub fn unexpected_last(&self, t: &token::Token) -> ! { + self.span_fatal( + *self.last_span, + fmt!( + "unexpected token: `%s`", + self.token_to_str(t) + ) + ); + } + + pub fn unexpected(&self) -> ! { + self.fatal( + fmt!( + "unexpected token: `%s`", + self.this_token_to_str() + ) + ); + } + + // expect and consume the token t. Signal an error if + // the next token is not t. + pub fn expect(&self, t: &token::Token) { + if *self.token == *t { + self.bump(); + } else { + self.fatal( + fmt!( + "expected `%s` but found `%s`", + self.token_to_str(t), + self.this_token_to_str() + ) + ) + } + } + + pub fn parse_ident(&self) -> ast::ident { + self.check_strict_keywords(); + self.check_reserved_keywords(); + match *self.token { + token::IDENT(i, _) => { + self.bump(); + i + } + token::INTERPOLATED(token::nt_ident(*)) => { + self.bug("ident interpolation not converted to real token"); + } + _ => { + self.fatal( + fmt!( + "expected ident, found `%s`", + self.this_token_to_str() + ) + ); + } + } + } + + pub fn parse_path_list_ident(&self) -> ast::path_list_ident { + let lo = self.span.lo; + let ident = self.parse_ident(); + let hi = self.last_span.hi; + spanned(lo, hi, ast::path_list_ident_ { name: ident, + id: self.get_id() }) + } + + // consume token 'tok' if it exists. Returns true if the given + // token was present, false otherwise. + pub fn eat(&self, tok: &token::Token) -> bool { + return if *self.token == *tok { self.bump(); true } else { false }; + } + + pub fn is_keyword(&self, kw: keywords::Keyword) -> bool { + token::is_keyword(kw, self.token) + } + + // if the next token is the given keyword, eat it and return + // true. Otherwise, return false. + pub fn eat_keyword(&self, kw: keywords::Keyword) -> bool { + let is_kw = match *self.token { + token::IDENT(sid, false) => kw.to_ident().name == sid.name, + _ => false + }; + if is_kw { self.bump() } + is_kw + } + + // if the given word is not a keyword, signal an error. + // if the next token is not the given word, signal an error. + // otherwise, eat it. + pub fn expect_keyword(&self, kw: keywords::Keyword) { + if !self.eat_keyword(kw) { + self.fatal( + fmt!( + "expected `%s`, found `%s`", + *self.id_to_str(kw.to_ident()), + self.this_token_to_str() + ) + ); + } + } + + // signal an error if the given string is a strict keyword + pub fn check_strict_keywords(&self) { + if token::is_strict_keyword(self.token) { + self.span_err(*self.last_span, + fmt!("found `%s` in ident position", self.this_token_to_str())); + } + } + + // signal an error if the current token is a reserved keyword + pub fn check_reserved_keywords(&self) { + if token::is_reserved_keyword(self.token) { + self.fatal(fmt!("`%s` is a reserved keyword", self.this_token_to_str())); + } + } + + // expect and consume a GT. if a >> is seen, replace it + // with a single > and continue. If a GT is not seen, + // signal an error. + pub fn expect_gt(&self) { + if *self.token == token::GT { + self.bump(); + } else if *self.token == token::BINOP(token::SHR) { + self.replace_token( + token::GT, + self.span.lo + BytePos(1u), + self.span.hi + ); + } else { + let mut s: ~str = ~"expected `"; + s.push_str(self.token_to_str(&token::GT)); + s.push_str("`, found `"); + s.push_str(self.this_token_to_str()); + s.push_str("`"); + self.fatal(s); + } + } + + // parse a sequence bracketed by '<' and '>', stopping + // before the '>'. + pub fn parse_seq_to_before_gt(&self, + sep: Option, + f: &fn(&Parser) -> T) + -> OptVec { + let mut first = true; + let mut v = opt_vec::Empty; + while *self.token != token::GT + && *self.token != token::BINOP(token::SHR) { + match sep { + Some(ref t) => { + if first { first = false; } + else { self.expect(t); } + } + _ => () + } + v.push(f(self)); + } + return v; + } + + pub fn parse_seq_to_gt(&self, + sep: Option, + f: &fn(&Parser) -> T) + -> OptVec { + let v = self.parse_seq_to_before_gt(sep, f); + self.expect_gt(); + return v; + } + + // parse a sequence, including the closing delimiter. The function + // f must consume tokens until reaching the next separator or + // closing bracket. + pub fn parse_seq_to_end(&self, + ket: &token::Token, + sep: SeqSep, + f: &fn(&Parser) -> T) + -> ~[T] { + let val = self.parse_seq_to_before_end(ket, sep, f); + self.bump(); + val + } + + // parse a sequence, not including the closing delimiter. The function + // f must consume tokens until reaching the next separator or + // closing bracket. + pub fn parse_seq_to_before_end(&self, + ket: &token::Token, + sep: SeqSep, + f: &fn(&Parser) -> T) + -> ~[T] { + let mut first: bool = true; + let mut v: ~[T] = ~[]; + while *self.token != *ket { + match sep.sep { + Some(ref t) => { + if first { first = false; } + else { self.expect(t); } + } + _ => () + } + if sep.trailing_sep_allowed && *self.token == *ket { break; } + v.push(f(self)); + } + return v; + } + + // parse a sequence, including the closing delimiter. The function + // f must consume tokens until reaching the next separator or + // closing bracket. + pub fn parse_unspanned_seq(&self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: &fn(&Parser) -> T) + -> ~[T] { + self.expect(bra); + let result = self.parse_seq_to_before_end(ket, sep, f); + self.bump(); + result + } + + // NB: Do not use this function unless you actually plan to place the + // spanned list in the AST. + pub fn parse_seq(&self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: &fn(&Parser) -> T) + -> spanned<~[T]> { + let lo = self.span.lo; + self.expect(bra); + let result = self.parse_seq_to_before_end(ket, sep, f); + let hi = self.span.hi; + self.bump(); + spanned(lo, hi, result) + } + // advance the parser by one token pub fn bump(&self) { *self.last_span = copy *self.span; From 9bfe2a7340e502c3e742f56b483d64d1a5dbf5a5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 14 Jun 2013 19:40:11 -0700 Subject: [PATCH 12/13] librustc: Fix merge fallout. --- src/librustc/back/link.rs | 2 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/lang_items.rs | 2 +- src/librustc/middle/reachable.rs | 16 ++++++++-------- src/librustc/middle/resolve.rs | 6 +++--- src/librustc/middle/trans/asm.rs | 2 +- src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/trans/common.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 10 ++++------ src/librustc/middle/typeck/check/regionck.rs | 19 ++++++++----------- src/librusti/rusti.rc | 10 +++------- src/libstd/path.rs | 2 +- src/libstd/str.rs | 6 ++++-- src/libsyntax/ext/pipes/pipec.rs | 2 +- src/libsyntax/parse/parser.rs | 2 +- 15 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 5dfc2f5fe3ea4..b695004736f30 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -685,7 +685,7 @@ pub fn mangle(sess: Session, ss: path) -> ~str { for ss.each |s| { match *s { path_name(s) | path_mod(s) => { - let sani = sanitize(*sess.str_of(s)); + let sani = sanitize(sess.str_of(s)); n.push_str(fmt!("%u%s", sani.len(), sani)); } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index c3f86930a002f..8f6c2afc42989 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1130,7 +1130,7 @@ fn encode_info_for_items(ecx: @EncodeContext, ast_map::path_to_str( *pt, token::get_ident_interner()), - *token::ident_to_str(&ni.ident)); + token::ident_to_str(&ni.ident)); let mut ebml_w = copy ebml_w; encode_info_for_foreign_item(ecx, diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 7f1b983a623bd..b05f1f61e8ba2 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -298,7 +298,7 @@ fn LanguageItemCollector(crate: @crate, item_refs.insert(@"annihilate", AnnihilateFnLangItem as uint); item_refs.insert(@"log_type", LogTypeFnLangItem as uint); item_refs.insert(@"fail_", FailFnLangItem as uint); - item_refs.insert(@"fail_bounds_check", + item_refs.insert(@"fail_bounds_check", FailBoundsCheckFnLangItem as uint); item_refs.insert(@"exchange_malloc", ExchangeMallocFnLangItem as uint); item_refs.insert(@"exchange_free", ExchangeFreeFnLangItem as uint); item_refs.insert(@"malloc", MallocFnLangItem as uint); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 1361f2c245afc..106c1d85cd77f 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -109,7 +109,7 @@ impl ReachableContext { let reachable_symbols = self.reachable_symbols; let worklist = self.worklist; let visitor = visit::mk_vt(@Visitor { - visit_item: |item, _, visitor| { + visit_item: |item, (_, visitor)| { match item.node { item_fn(*) => { reachable_symbols.insert(item.id); @@ -184,13 +184,13 @@ impl ReachableContext { } if item.vis == public { - visit::visit_item(item, (), visitor) + visit::visit_item(item, ((), visitor)) } }, .. *visit::default_visitor() }); - visit::visit_crate(crate, (), visitor) + visit::visit_crate(crate, ((), visitor)) } // Returns true if the given def ID represents a local item that is @@ -256,7 +256,7 @@ impl ReachableContext { let (worklist, method_map) = (self.worklist, self.method_map); let (tcx, reachable_symbols) = (self.tcx, self.reachable_symbols); visit::mk_vt(@visit::Visitor { - visit_expr: |expr, _, visitor| { + visit_expr: |expr, (_, visitor)| { match expr.node { expr_path(_) => { let def = match tcx.def_map.find(&expr.id) { @@ -300,7 +300,7 @@ impl ReachableContext { _ => {} } - visit::visit_expr(expr, (), visitor) + visit::visit_expr(expr, ((), visitor)) }, ..*visit::default_visitor() }) @@ -325,7 +325,7 @@ impl ReachableContext { Some(&ast_map::node_item(item, _)) => { match item.node { item_fn(_, _, _, _, ref search_block) => { - visit::visit_block(search_block, (), visitor) + visit::visit_block(search_block, ((), visitor)) } _ => { self.tcx.sess.span_bug(item.span, @@ -342,12 +342,12 @@ impl ReachableContext { worklist?!") } provided(ref method) => { - visit::visit_block(&method.body, (), visitor) + visit::visit_block(&method.body, ((), visitor)) } } } Some(&ast_map::node_method(ref method, _, _)) => { - visit::visit_block(&method.body, (), visitor) + visit::visit_block(&method.body, ((), visitor)) } Some(_) => { let ident_interner = token::get_ident_interner(); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 584daadd305c1..20480532c24f9 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1285,7 +1285,7 @@ impl Resolver { } item_impl(_, Some(_), ty, ref methods) => { - visit_item(item, parent, visitor); + visit_item(item, (parent, visitor)); } item_trait(_, _, ref methods) => { @@ -1335,7 +1335,7 @@ impl Resolver { match ty_m.explicit_self.node { sty_static => {} _ => { - method_names.insert(ident); + method_names.insert(ident, ()); } } } @@ -2039,7 +2039,7 @@ impl Resolver { } else { result.push_str("::") } - result.push_str(*self.session.str_of(*ident)); + result.push_str(self.session.str_of(*ident)); }; return result; } diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index dfc7abcbf49d6..4e61630615af9 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -93,7 +93,7 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block { if !ia.clobbers.is_empty() && !clobbers.is_empty() { clobbers = fmt!("%s,%s", ia.clobbers, clobbers); } else { - clobbers.push_str(*ia.clobbers); + clobbers.push_str(ia.clobbers); }; // Add the clobbers to our constraints list diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 9872470366b1d..c0fd9cc4c60e4 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -3015,7 +3015,7 @@ pub fn trans_crate(sess: session::Session, emap2: resolve::ExportMap2, reachable_map: @mut HashSet, maps: astencode::Maps) - -> (ContextRef, ModuleRef, LinkMeta) { + -> (ModuleRef, LinkMeta) { let symbol_hasher = @mut hash::default_state(); let link_meta = link::build_link_meta(sess, crate, output, symbol_hasher); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index dfc3e05a10563..0ebba87432de9 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1422,7 +1422,7 @@ pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str { } else { r.push_str("::") } - r.push_str(*sess.str_of(s)); + r.push_str(sess.str_of(s)); } } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index baa45a20ee05d..95715462bad0d 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -800,9 +800,8 @@ impl FnCtxt { match self.inh.node_types.find(&ex.id) { Some(&t) => t, None => { - self.tcx().sess.bug( - fmt!("no type for %s in fcx %s", - self.expr_to_str(ex), self.tag())); + self.tcx().sess.bug(fmt!("no type for expr in fcx %s", + self.tag())); } } } @@ -1142,7 +1141,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, expr: @ast::expr, expected: Option, unifier: &fn()) { - debug!(">> typechecking %s", fcx.expr_to_str(expr)); + debug!(">> typechecking"); fn check_method_argument_types( fcx: @mut FnCtxt, @@ -1730,8 +1729,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ty::mk_closure(tcx, fn_ty_copy) }; - debug!("check_expr_fn_with_unifier %s fty=%s", - fcx.expr_to_str(expr), + debug!("check_expr_fn_with_unifier fty=%s", fcx.infcx().ty_to_str(fty)); fcx.write_ty(expr.id, fty); diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 63a13789194cb..cbf9b5c38741e 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -231,7 +231,7 @@ fn constrain_bindings_in_pat(pat: @ast::pat, rcx: @mut Rcx) { } fn visit_expr(expr: @ast::expr, (rcx, v): (@mut Rcx, rvt)) { - debug!("regionck::visit_expr(e=%s)", rcx.fcx.expr_to_str(expr)); + debug!("regionck::visit_expr(e=?)"); let has_method_map = rcx.fcx.inh.method_map.contains_key(&expr.id); @@ -521,8 +521,7 @@ fn constrain_derefs(rcx: @mut Rcx, let tcx = rcx.fcx.tcx(); let r_deref_expr = ty::re_scope(deref_expr.id); for uint::range(0, derefs) |i| { - debug!("constrain_derefs(deref_expr=%s, derefd_ty=%s, derefs=%?/%?", - rcx.fcx.expr_to_str(deref_expr), + debug!("constrain_derefs(deref_expr=?, derefd_ty=%s, derefs=%?/%?", rcx.fcx.infcx().ty_to_str(derefd_ty), i, derefs); @@ -577,8 +576,7 @@ fn constrain_index(rcx: @mut Rcx, let tcx = rcx.fcx.tcx(); - debug!("constrain_index(index_expr=%s, indexed_ty=%s", - rcx.fcx.expr_to_str(index_expr), + debug!("constrain_index(index_expr=?, indexed_ty=%s", rcx.fcx.infcx().ty_to_str(indexed_ty)); let r_index_expr = ty::re_scope(index_expr.id); @@ -809,7 +807,7 @@ pub mod guarantor { * to the lifetime of its guarantor (if any). */ - debug!("guarantor::for_addr_of(base=%s)", rcx.fcx.expr_to_str(base)); + debug!("guarantor::for_addr_of(base=?)"); let guarantor = guarantor(rcx, base); link(rcx, expr.span, expr.id, guarantor); @@ -843,8 +841,7 @@ pub mod guarantor { * region pointers. */ - debug!("guarantor::for_autoref(expr=%s, autoref=%?)", - rcx.fcx.expr_to_str(expr), autoref); + debug!("guarantor::for_autoref(autoref=%?)", autoref); let mut expr_ct = categorize_unadjusted(rcx, expr); debug!(" unadjusted cat=%?", expr_ct.cat); @@ -971,7 +968,7 @@ pub mod guarantor { * `&expr`). */ - debug!("guarantor(expr=%s)", rcx.fcx.expr_to_str(expr)); + debug!("guarantor()"); match expr.node { ast::expr_unary(_, ast::deref, b) => { let cat = categorize(rcx, b); @@ -1035,7 +1032,7 @@ pub mod guarantor { } fn categorize(rcx: @mut Rcx, expr: @ast::expr) -> ExprCategorization { - debug!("categorize(expr=%s)", rcx.fcx.expr_to_str(expr)); + debug!("categorize()"); let mut expr_ct = categorize_unadjusted(rcx, expr); debug!("before adjustments, cat=%?", expr_ct.cat); @@ -1087,7 +1084,7 @@ pub mod guarantor { fn categorize_unadjusted(rcx: @mut Rcx, expr: @ast::expr) -> ExprCategorizationType { - debug!("categorize_unadjusted(expr=%s)", rcx.fcx.expr_to_str(expr)); + debug!("categorize_unadjusted()"); let guarantor = { if rcx.fcx.inh.method_map.contains_key(&expr.id) { diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 0d05c990d2977..c7645b3c414e1 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -380,13 +380,9 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, for loaded_crates.each |crate| { let crate_path = Path(*crate); let crate_dir = crate_path.dirname(); - let crate_name = crate_path.filename().get(); - if !repl.view_items.contains(*crate) { - repl.view_items.push_str(fmt!("extern mod %s;\n", - crate_name)); - if !repl.lib_search_paths.contains(&crate_dir) { - repl.lib_search_paths.push(crate_dir); - } + repl.program.record_extern(fmt!("extern mod %s;", *crate)); + if !repl.lib_search_paths.contains(&crate_dir) { + repl.lib_search_paths.push(crate_dir); } } if loaded_crates.is_empty() { diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 7363e51d23beb..62ca667f7f5e9 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -21,7 +21,7 @@ use cmp::Eq; use iterator::IteratorUtil; use libc; use option::{None, Option, Some}; -use str::{Str, StrSlice, StrVector}; +use str::{OwnedStr, Str, StrSlice, StrVector}; use str; use to_str::ToStr; use ascii::{AsciiCast, AsciiStr}; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index de680e61c3976..ade733c873cc9 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1579,7 +1579,8 @@ impl<'self> StrSlice<'self> for &'self str { fn slice_chars(&self, begin: uint, end: uint) -> &'self str { assert!(begin <= end); // not sure how to use the iterators for this nicely. - let mut (position, count) = (0, 0); + let mut position = 0; + let mut count = 0; let l = self.len(); while count < begin && position < l { position = self.char_range_at(position).next; @@ -1727,7 +1728,8 @@ impl<'self> StrSlice<'self> for &'self str { * The original string with all occurances of `from` replaced with `to` */ pub fn replace(&self, from: &str, to: &str) -> ~str { - let mut (result, last_end) = (~"", 0); + let mut result = ~""; + let mut last_end = 0; for self.matches_index_iter(from).advance |(start, end)| { result.push_str(unsafe{raw::slice_bytes(*self, last_end, start)}); result.push_str(to); diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 6269cafdd2960..745f8c7c92246 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -101,7 +101,7 @@ impl gen_send for message { } body.push_str(fmt!("let message = %s(%s);\n", name, - vec::append_one(arg_names.map(|x| cx.str_of(*x)), ~"s") + vec::append_one(arg_names.map(|x| cx.str_of(*x)), @"s") .connect(", "))); if !try { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d5ebc6635be02..a612c0f379160 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -381,7 +381,7 @@ impl Parser { self.fatal( fmt!( "expected `%s`, found `%s`", - *self.id_to_str(kw.to_ident()), + self.id_to_str(kw.to_ident()).to_str(), self.this_token_to_str() ) ); From 35b61c47216c8a3cd6a0a36a644bd66bf902d617 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 13 Jun 2013 10:07:34 -0700 Subject: [PATCH 13/13] rustc: map node ids through a table that ensures bitset indexes in dataflow are dense --- src/librustc/middle/borrowck/check_loans.rs | 4 +- src/librustc/middle/borrowck/move_data.rs | 4 +- src/librustc/middle/dataflow.rs | 91 ++++++++++++++++----- 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index dfbef30f896d6..61c1a3b72d613 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -83,7 +83,7 @@ impl<'self> CheckLoanCtxt<'self> { //! are issued for future scopes and thus they may have been //! *issued* but not yet be in effect. - for self.dfcx_loans.each_bit_on_entry(scope_id) |loan_index| { + for self.dfcx_loans.each_bit_on_entry_frozen(scope_id) |loan_index| { let loan = &self.all_loans[loan_index]; if !op(loan) { return false; @@ -135,7 +135,7 @@ impl<'self> CheckLoanCtxt<'self> { //! we encounter `scope_id`. let mut result = ~[]; - for self.dfcx_loans.each_gen_bit(scope_id) |loan_index| { + for self.dfcx_loans.each_gen_bit_frozen(scope_id) |loan_index| { result.push(loan_index); } return result; diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index 6b16bb5a3c358..2cc718d4fabf1 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -505,7 +505,7 @@ impl FlowedMoveData { let opt_loan_path_index = self.move_data.existing_move_path(loan_path); - for self.dfcx_moves.each_bit_on_entry(id) |index| { + for self.dfcx_moves.each_bit_on_entry_frozen(id) |index| { let move = &self.move_data.moves[index]; let moved_path = move.path; if base_indices.contains(&moved_path) { @@ -561,7 +561,7 @@ impl FlowedMoveData { } }; - for self.dfcx_assign.each_bit_on_entry(id) |index| { + for self.dfcx_assign.each_bit_on_entry_frozen(id) |index| { let assignment = &self.move_data.var_assignments[index]; if assignment.path == loan_path_index && !f(assignment) { return false; diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 530f166098453..294eaac6a73ce 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -23,6 +23,7 @@ use core::cast; use core::io; use core::uint; use core::vec; +use core::hashmap::HashMap; use syntax::ast; use syntax::ast_util; use syntax::ast_util::id_range; @@ -38,9 +39,6 @@ pub struct DataFlowContext { /// the data flow operator priv oper: O, - /// range of ids that appear within the item in question - priv id_range: id_range, - /// number of bits to propagate per id priv bits_per_id: uint, @@ -48,6 +46,9 @@ pub struct DataFlowContext { /// equal to bits_per_id/uint::bits rounded up. priv words_per_id: uint, + // mapping from node to bitset index. + priv nodeid_to_bitset: HashMap, + // Bit sets per id. The following three fields (`gens`, `kills`, // and `on_entry`) all have the same structure. For each id in // `id_range`, there is a range of words equal to `words_per_id`. @@ -109,19 +110,17 @@ impl DataFlowContext { debug!("DataFlowContext::new(id_range=%?, bits_per_id=%?, words_per_id=%?)", id_range, bits_per_id, words_per_id); - let len = (id_range.max - id_range.min) as uint * words_per_id; - let gens = vec::from_elem(len, 0); - let kills = vec::from_elem(len, 0); - let elem = if oper.initial_value() {uint::max_value} else {0}; - let on_entry = vec::from_elem(len, elem); + let gens = ~[]; + let kills = ~[]; + let on_entry = ~[]; DataFlowContext { tcx: tcx, method_map: method_map, words_per_id: words_per_id, + nodeid_to_bitset: HashMap::new(), bits_per_id: bits_per_id, oper: oper, - id_range: id_range, gens: gens, kills: kills, on_entry: on_entry @@ -150,7 +149,7 @@ impl DataFlowContext { } } - fn apply_gen_kill(&self, id: ast::node_id, bits: &mut [uint]) { + fn apply_gen_kill(&mut self, id: ast::node_id, bits: &mut [uint]) { //! Applies the gen and kill sets for `id` to `bits` debug!("apply_gen_kill(id=%?, bits=%s) [before]", @@ -165,7 +164,7 @@ impl DataFlowContext { id, mut_bits_to_str(bits)); } - fn apply_kill(&self, id: ast::node_id, bits: &mut [uint]) { + fn apply_kill(&mut self, id: ast::node_id, bits: &mut [uint]) { debug!("apply_kill(id=%?, bits=%s) [before]", id, mut_bits_to_str(bits)); let (start, end) = self.compute_id_range(id); @@ -175,18 +174,56 @@ impl DataFlowContext { id, mut_bits_to_str(bits)); } - fn compute_id_range(&self, absolute_id: ast::node_id) -> (uint, uint) { - assert!(absolute_id >= self.id_range.min); - assert!(absolute_id < self.id_range.max); + fn compute_id_range_frozen(&self, id: ast::node_id) -> (uint, uint) { + let n = *self.nodeid_to_bitset.get(&id); + let start = n * self.words_per_id; + let end = start + self.words_per_id; + (start, end) + } - let relative_id = absolute_id - self.id_range.min; - let start = (relative_id as uint) * self.words_per_id; + fn compute_id_range(&mut self, id: ast::node_id) -> (uint, uint) { + let mut expanded = false; + let len = self.nodeid_to_bitset.len(); + let n = do self.nodeid_to_bitset.find_or_insert_with(id) |_| { + expanded = true; + len + }; + if expanded { + let entry = if self.oper.initial_value() { uint::max_value } else {0}; + for self.words_per_id.times { + self.gens.push(0); + self.kills.push(0); + self.on_entry.push(entry); + } + } + let start = *n * self.words_per_id; let end = start + self.words_per_id; + + assert!(start < self.gens.len()); + assert!(end <= self.gens.len()); + assert!(self.gens.len() == self.kills.len()); + assert!(self.gens.len() == self.on_entry.len()); + (start, end) } - pub fn each_bit_on_entry(&self, + pub fn each_bit_on_entry_frozen(&self, + id: ast::node_id, + f: &fn(uint) -> bool) -> bool { + //! Iterates through each bit that is set on entry to `id`. + //! Only useful after `propagate()` has been called. + if !self.nodeid_to_bitset.contains_key(&id) { + return true; + } + let (start, end) = self.compute_id_range_frozen(id); + let on_entry = vec::slice(self.on_entry, start, end); + debug!("each_bit_on_entry_frozen(id=%?, on_entry=%s)", + id, bits_to_str(on_entry)); + self.each_bit(on_entry, f) + } + + pub fn each_bit_on_entry(&mut self, id: ast::node_id, f: &fn(uint) -> bool) -> bool { //! Iterates through each bit that is set on entry to `id`. @@ -199,7 +236,7 @@ impl DataFlowContext { self.each_bit(on_entry, f) } - pub fn each_gen_bit(&self, + pub fn each_gen_bit(&mut self, id: ast::node_id, f: &fn(uint) -> bool) -> bool { //! Iterates through each bit in the gen set for `id`. @@ -211,6 +248,20 @@ impl DataFlowContext { self.each_bit(gens, f) } + pub fn each_gen_bit_frozen(&self, + id: ast::node_id, + f: &fn(uint) -> bool) -> bool { + //! Iterates through each bit in the gen set for `id`. + if !self.nodeid_to_bitset.contains_key(&id) { + return true; + } + let (start, end) = self.compute_id_range_frozen(id); + let gens = vec::slice(self.gens, start, end); + debug!("each_gen_bit(id=%?, gens=%s)", + id, bits_to_str(gens)); + self.each_bit(gens, f) + } + fn each_bit(&self, words: &[uint], f: &fn(uint) -> bool) -> bool { @@ -286,8 +337,8 @@ impl DataFlowContext { pprust::node_pat(ps, pat) => (ps, pat.id) }; - if id >= self.id_range.min || id < self.id_range.max { - let (start, end) = self.compute_id_range(id); + if self.nodeid_to_bitset.contains_key(&id) { + let (start, end) = self.compute_id_range_frozen(id); let on_entry = vec::slice(self.on_entry, start, end); let entry_str = bits_to_str(on_entry);