From cf9ca95ff6d5cceba5d061720fecfffb7f32d8da Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Jun 2013 11:33:14 -0700 Subject: [PATCH 01/18] 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 | 21 ++++++------ src/librustc/middle/lang_items.rs | 24 +++++++------- src/librustc/middle/ty.rs | 46 ++++++++++++++------------- src/librustc/middle/typeck/astconv.rs | 8 ++--- src/librustc/util/ppaux.rs | 4 +-- src/libstd/kinds.rs | 9 +++++- 9 files changed, 65 insertions(+), 53 deletions(-) diff --git a/src/libextra/rc.rs b/src/libextra/rc.rs index 8ef58a188d930..b0ff2653f81a5 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, } @@ -167,6 +168,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 c3840c9c87fb2..fe5ac8335f4fb 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 37fedc16122e5..7c8741b41d985 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -401,7 +401,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 ef96fa979727a..7a615601b1e89 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -33,7 +33,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. @@ -90,10 +90,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 \ @@ -101,7 +101,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 \ @@ -438,10 +438,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 { @@ -489,7 +489,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. @@ -528,7 +528,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( @@ -574,3 +574,4 @@ pub fn check_cast_for_escaping_regions( cx.tcx.region_maps.is_subregion_of(r_sub, r_sup) } } + diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index cd6070cc638f0..8b9a3c6bdae85 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". // @@ -33,9 +33,9 @@ use syntax::visit::visit_crate; use core::hashmap::HashMap; pub enum LangItem { - ConstTraitLangItem, // 0 + FreezeTraitLangItem, // 0 CopyTraitLangItem, // 1 - OwnedTraitLangItem, // 2 + SendTraitLangItem, // 2 SizedTraitLangItem, // 3 DropTraitLangItem, // 4 @@ -101,7 +101,7 @@ impl LanguageItems { match index { 0 => "const", 1 => "copy", - 2 => "owned", + 2 => "send", 3 => "sized", 4 => "drop", @@ -152,14 +152,14 @@ 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() } - 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() @@ -291,13 +291,13 @@ struct LanguageItemCollector<'self> { } impl<'self> LanguageItemCollector<'self> { - - pub fn new<'a>(crate: &'a crate, session: Session) -> LanguageItemCollector<'a> { + pub fn new<'a>(crate: &'a crate, session: Session) + -> LanguageItemCollector<'a> { let mut item_refs = HashMap::new(); - item_refs.insert(@"const", ConstTraitLangItem as uint); + item_refs.insert(@"const", FreezeTraitLangItem as uint); item_refs.insert(@"copy", CopyTraitLangItem as uint); - item_refs.insert(@"owned", OwnedTraitLangItem as uint); + item_refs.insert(@"owned", SendTraitLangItem as uint); item_refs.insert(@"sized", SizedTraitLangItem as uint); item_refs.insert(@"drop", DropTraitLangItem as uint); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index d34befddad5f7..07caa35f571f9 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 @@ -1839,7 +1839,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), } } @@ -1865,12 +1865,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 { @@ -1912,8 +1912,8 @@ impl TypeContents { 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_POINTER + TC_OWNED_VEC } } @@ -1969,8 +1969,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}; @@ -1986,8 +1986,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 { @@ -2045,7 +2045,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 @@ -2060,7 +2060,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(_, _, store, mutbl, bounds) => { @@ -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(_)) => { @@ -2205,8 +2207,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 } @@ -2227,7 +2229,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 @@ -2314,7 +2316,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { tc = tc - match bound { BoundCopy => TypeContents::noncopyable(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 b7242e64f230b..0608d27cf6ce1 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -753,7 +753,7 @@ fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option 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 3194df269c0e3..559d478e7638e 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -575,7 +575,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", }); @@ -781,7 +781,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 dda2b7bb34555e897b2ef0094b1ca52049f1e0e9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Jun 2013 14:52:27 -0700 Subject: [PATCH 02/18] 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 | 6 +++--- 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, 34 insertions(+), 27 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index fe5ac8335f4fb..ba19e7e6eb2b7 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 7c8741b41d985..0f9937fd3c0cf 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -403,7 +403,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 7a615601b1e89..f0c091ac53cae 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -31,7 +31,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. // @@ -40,12 +40,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 8b9a3c6bdae85..3418fc649da0e 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. @@ -99,7 +99,7 @@ impl LanguageItems { pub fn item_name(index: uint) -> &'static str { match index { - 0 => "const", + 0 => "freeze", 1 => "copy", 2 => "send", 3 => "sized", diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 07caa35f571f9..984bc8236a7a3 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 } @@ -1838,7 +1838,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), } @@ -1877,11 +1877,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 } @@ -1990,8 +1990,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 { @@ -2045,7 +2045,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 @@ -2317,7 +2317,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { BoundCopy => TypeContents::noncopyable(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 0608d27cf6ce1..70df9877162eb 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -818,8 +818,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 559d478e7638e..58dc121959ed2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -576,7 +576,7 @@ impl Repr for ty::ParamBounds { ty::BoundCopy => ~"Copy", ty::BoundStatic => ~"'static", ty::BoundSend => ~"Send", - ty::BoundConst => ~"Const", + ty::BoundFreeze => ~"Freeze", ty::BoundSized => ~"Sized", }); } @@ -782,7 +782,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 6d7cb2a28a88d..8e240a62236f4 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 4ca49044fa4fe7a88a24be38d2ec4f701b6a3e2e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Jun 2013 15:53:17 -0700 Subject: [PATCH 03/18] librustc: Rename Const to Freeze --- src/libextra/arc.rs | 20 +++++++++---------- src/libextra/rc.rs | 8 ++++---- 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/token.rs | 2 +- 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 +- 19 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs index c04ee63880e99..c3b7fadf0b99a 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() } } @@ -282,14 +282,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 { @@ -299,7 +299,7 @@ pub fn rw_arc_with_condvars( RWARC { x: UnsafeAtomicRcBox::new(data), } } -impl RWARC { +impl RWARC { /// Duplicate a rwlock-protected ARC, as arc::clone. pub fn clone(&self) -> RWARC { RWARC { @@ -309,7 +309,7 @@ impl RWARC { } -impl RWARC { +impl RWARC { /** * Access the underlying data mutably. Locks the rwlock in write mode; * other readers and writers will block. @@ -435,7 +435,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) } } @@ -452,7 +452,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 { @@ -493,7 +493,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 b0ff2653f81a5..31bee61b6a1b7 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) } } @@ -189,7 +189,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/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 bedb465c5c14c..a867ea948025f 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 0e118adb8f42e..94520b6faca65 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1165,7 +1165,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 6622ea1551bf9..ca167c3726ae2 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" @@ -786,7 +786,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 046693632c604..4a85a8c871d6d 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 { @@ -113,16 +113,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] 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] 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 8e240a62236f4..5959cdaf318c1 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 feb03896558e7..a9b0c3986f8b2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -147,7 +147,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/token.rs b/src/libsyntax/parse/token.rs index 2ddae73a3fcd9..df599596d7d00 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -563,7 +563,7 @@ pub mod keywords { // Strict keywords As, Break, - Const, + Freeze, Copy, Do, Else, diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index af37c1d27d821..3cdc4fd0fa106 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -21,7 +21,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 d4f6a1ec4040c..8c491a4dfc83b 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 drop(&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 76698a0ee9e3603a69f3980f3d72c9062ca55601 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Jun 2013 17:56:24 -0700 Subject: [PATCH 04/18] 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 | 4 +- 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, 222 insertions(+), 222 deletions(-) diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs index c3b7fadf0b99a..8e7ba940b8ec0 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 @@ -282,14 +282,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 { @@ -299,7 +299,7 @@ pub fn rw_arc_with_condvars( RWARC { x: UnsafeAtomicRcBox::new(data), } } -impl RWARC { +impl RWARC { /// Duplicate a rwlock-protected ARC, as arc::clone. pub fn clone(&self) -> RWARC { RWARC { @@ -309,7 +309,7 @@ impl RWARC { } -impl RWARC { +impl RWARC { /** * Access the underlying data mutably. Locks the rwlock in write mode; * other readers and writers will block. @@ -435,7 +435,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) } } @@ -452,7 +452,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 { @@ -493,7 +493,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 60fbfdeb62c16..d5e43e85a140e 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 f2cd64085efff..00f4cc3989be3 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 334ab7c9c990f..a3014cf8894bf 100644 --- a/src/libextra/par.rs +++ b/src/libextra/par.rs @@ -33,7 +33,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] { @@ -88,7 +88,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(); @@ -99,7 +99,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, || { @@ -118,7 +118,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 { @@ -133,7 +133,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 31bee61b6a1b7..46d206e5dc767 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) } } @@ -184,7 +184,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 8cfe39c5ef25e..f5db15c6059da 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -86,7 +86,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 })) } @@ -101,7 +101,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; @@ -175,7 +175,7 @@ struct SemReleaseGeneric<'self, Q> { sem: &'self Sem } #[doc(hidden)] #[unsafe_destructor] -impl<'self, Q:Owned> Drop for SemReleaseGeneric<'self, Q> { +impl<'self, Q:Send> Drop for SemReleaseGeneric<'self, Q> { fn drop(&self) { self.sem.release(); } diff --git a/src/libextra/timer.rs b/src/libextra/timer.rs index 71d8a5d81e7e4..5a622ddfa0deb 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 a014293f0630d..567f9eda2fbae 100644 --- a/src/libextra/workcache.rs +++ b/src/libextra/workcache.rs @@ -272,7 +272,7 @@ impl Context { } } - pub fn prep + Decodable>(@self, // FIXME(#5121) fn_name:&str, @@ -292,7 +292,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; @@ -328,7 +328,7 @@ impl TPrep for Prep { return true; } - fn exec + Decodable>( // FIXME(#5121) &self, blk: ~fn(&Exec) -> T) -> Work { @@ -365,7 +365,7 @@ impl TPrep for Prep { } } -impl + Decodable> Work { // FIXME(#5121) pub fn new(p: @mut Prep, e: Either>) -> Work { @@ -374,7 +374,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 a867ea948025f..5f4251ad0a424 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 de6b792032b1b..58a527f35018d 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -538,7 +538,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); @@ -624,7 +624,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 => { @@ -641,7 +641,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); @@ -651,4 +651,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 3775aafb56969..27ab3aca02093 100644 --- a/src/librustdoc/astsrv.rs +++ b/src/librustdoc/astsrv.rs @@ -99,7 +99,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 1c34007c99d42..a2e50d37fb63e 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 4a85a8c871d6d..947aa5708c296 100644 --- a/src/libstd/clone.rs +++ b/src/libstd/clone.rs @@ -112,7 +112,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. @@ -120,7 +120,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 7918abe4ae6a9..8316a33ecf1f8 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::OwnedVector; @@ -77,7 +77,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)) @@ -91,7 +91,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), @@ -100,7 +100,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), @@ -109,7 +109,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(), @@ -125,7 +125,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(), @@ -134,7 +134,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(), @@ -149,7 +149,7 @@ pub struct PortSet { ports: ~[pipesy::Port], } -impl PortSet { +impl PortSet { pub fn new() -> PortSet { PortSet { ports: ~[] @@ -175,7 +175,7 @@ impl PortSet { } } -impl GenericPort for PortSet { +impl GenericPort for PortSet { fn try_recv(&self) -> Option { unsafe { let self_ports = transmute_mut(&self.ports); @@ -204,7 +204,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. @@ -223,7 +223,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; @@ -235,7 +235,7 @@ impl SharedChan { } } -impl GenericChan for SharedChan { +impl GenericChan for SharedChan { fn send(&self, x: T) { unsafe { let mut xx = Some(x); @@ -247,7 +247,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); @@ -259,7 +259,7 @@ impl GenericSmartChan for SharedChan { } } -impl ::clone::Clone for SharedChan { +impl ::clone::Clone for SharedChan { fn clone(&self) -> SharedChan { SharedChan { ch: self.ch.clone() } } @@ -273,7 +273,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)), @@ -287,7 +287,7 @@ pub fn oneshot() -> (PortOne, ChanOne) { return (port, chan); } -impl PortOne { +impl PortOne { pub fn recv(self) -> T { let PortOne { inner } = self; match inner { @@ -305,7 +305,7 @@ impl PortOne { } } -impl ChanOne { +impl ChanOne { pub fn send(self, data: T) { let ChanOne { inner } = self; match inner { @@ -323,7 +323,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), @@ -331,7 +331,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), @@ -339,7 +339,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), @@ -347,7 +347,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), @@ -357,7 +357,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}; @@ -365,17 +365,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 { @@ -399,10 +399,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; @@ -414,7 +414,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); @@ -464,12 +464,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 { @@ -479,7 +479,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 { @@ -493,7 +493,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); @@ -503,7 +503,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); @@ -519,7 +519,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), } @@ -529,7 +529,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() @@ -540,16 +540,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() } @@ -559,10 +559,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; @@ -575,7 +575,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(); @@ -613,7 +613,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 { @@ -623,7 +623,7 @@ mod pipesy { }) } - impl GenericChan for Chan { + impl GenericChan for Chan { #[inline] fn send(&self, x: T) { unsafe { @@ -634,7 +634,7 @@ mod pipesy { } } - impl GenericSmartChan for Chan { + impl GenericSmartChan for Chan { #[inline] fn try_send(&self, x: T) -> bool { unsafe { @@ -651,7 +651,7 @@ mod pipesy { } } - impl GenericPort for Port { + impl GenericPort for Port { #[inline] fn recv(&self) -> T { unsafe { @@ -679,7 +679,7 @@ mod pipesy { } } - impl Peekable for Port { + impl Peekable for Port { #[inline] fn peek(&self) -> bool { unsafe { @@ -695,7 +695,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(), @@ -723,15 +723,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 661dc2a659f74..49713a3a23b9a 100644 --- a/src/libstd/pipes.rs +++ b/src/libstd/pipes.rs @@ -88,7 +88,7 @@ use container::Container; use cast::{forget, transmute, transmute_copy, transmute_mut}; use either::{Either, Left, Right}; use iterator::IteratorUtil; -use kinds::Owned; +use kinds::Send; use libc; use ops::Drop; use option::{None, Option, Some}; @@ -177,7 +177,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); } @@ -193,13 +193,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, @@ -230,7 +230,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) { @@ -396,7 +396,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") } @@ -407,7 +407,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_ }; @@ -427,7 +427,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 => { @@ -511,7 +511,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, @@ -521,7 +521,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 }; @@ -553,7 +553,7 @@ fn sender_terminate(p: *mut Packet) { } } -fn receiver_terminate(p: *mut Packet) { +fn receiver_terminate(p: *mut Packet) { let p = unsafe { &mut *p }; @@ -671,7 +671,7 @@ pub struct SendPacketBuffered { } #[unsafe_destructor] -impl Drop for SendPacketBuffered { +impl Drop for SendPacketBuffered { fn drop(&self) { unsafe { let this: &mut SendPacketBuffered = transmute(self); @@ -729,7 +729,7 @@ pub struct RecvPacketBuffered { } #[unsafe_destructor] -impl Drop for RecvPacketBuffered { +impl Drop for RecvPacketBuffered { fn drop(&self) { unsafe { let this: &mut RecvPacketBuffered = transmute(self); @@ -741,7 +741,7 @@ impl Drop for RecvPacketBuffered { } } -impl RecvPacketBuffered { +impl RecvPacketBuffered { pub fn unwrap(&mut self) -> *mut Packet { replace(&mut self.p, None).unwrap() } @@ -751,7 +751,7 @@ impl RecvPacketBuffered { } } -impl Selectable for RecvPacketBuffered { +impl Selectable for RecvPacketBuffered { fn header(&mut self) -> *mut PacketHeader { match self.p { Some(packet) => unsafe { @@ -807,7 +807,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), @@ -847,7 +847,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 5959cdaf318c1..13d19b276f59e 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 75b1d8f38103d..72907f40a0744 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 4fde8f704b987..285a8114cc240 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 0f9298595eec7..06c3ecb814757 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 a9b0c3986f8b2..265e9e444e94a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -147,7 +147,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 d1d4d173a3f33..c9d63d2c41679 100644 --- a/src/libsyntax/ext/deriving/to_str.rs +++ b/src/libsyntax/ext/deriving/to_str.rs @@ -30,7 +30,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 2f21eba11d7e2..a2f9aa58d99ad 100644 --- a/src/libsyntax/ext/deriving/ty.rs +++ b/src/libsyntax/ext/deriving/ty.rs @@ -22,7 +22,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] } @@ -128,7 +128,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) => { @@ -248,7 +248,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 e45bfc8ea5dc3..beca0adbe3c5b 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(copy 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 887346e35e5ea..6ffdd0f541e14 100644 --- a/src/test/compile-fail/closure-bounds-subtype.rs +++ b/src/test/compile-fail/closure-bounds-subtype.rs @@ -5,7 +5,7 @@ fn take_any(_: &fn:()) { fn take_copyable(_: &fn:Copy()) { } -fn take_copyable_owned(_: &fn:Copy+Owned()) { +fn take_copyable_owned(_: &fn:Copy+Send()) { } fn take_const_owned(_: &fn:Const+Owned()) { @@ -14,22 +14,22 @@ fn take_const_owned(_: &fn:Const+Owned()) { 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 551b50c94f242..00d73b02dbc6e 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 drop(&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 753e5339de9da..24709fb297400 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) = || (copy a, copy 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 9fbca7d05720d..14915555889d0 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 drop(&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 drop(&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 7ac38966faa3e..11c43b9390198 100644 --- a/src/test/run-pass/pipe-bank-proto.rs +++ b/src/test/run-pass/pipe-bank-proto.rs @@ -45,8 +45,8 @@ proto! bank ( } ) -fn switch(endp: pipes::RecvPacket, - f: &fn(v: Option) -> U) -> U { +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 416e7bf82bb84..216a7a939fe05 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 7a95997ec92de7a7fe484bde25627a33da50d7af Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 6 Jun 2013 18:54:14 -0700 Subject: [PATCH 05/18] 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 | 3 +- 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 | 17 +++-- 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(+), 50 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 0939664fc79fa..c585cc5721312 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2862,13 +2862,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). @@ -2882,7 +2882,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. @@ -2968,10 +2968,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. @@ -3116,7 +3116,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 346112e655baf..047b57e56a61a 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 drop(&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 5d3d31fdec47e..f9eaa2bf02ddf 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -415,7 +415,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 4b080e0153ccc..08da4abf3fa4f 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -381,7 +381,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 @@ -443,7 +446,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 5a622ddfa0deb..79451db8b1715 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 ac51c7efc6f0c..45fdda1990cc8 100644 --- a/src/librustc/middle/trans/cabi_arm.rs +++ b/src/librustc/middle/trans/cabi_arm.rs @@ -139,12 +139,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: Type::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 8604ae37f7748..47f2fb8634c16 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -178,12 +178,14 @@ impl ABIInfo for MIPS_ABIInfo { atys: &[Type], rty: Type, 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: Type::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 14ab17f5030d6..23542ca905b9f 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -360,8 +360,9 @@ fn x86_64_tys(atys: &[Type], arg_tys.push(ty); attrs.push(attr); } - let mut (ret_ty, ret_attr) = x86_64_ty(rty, |cls| cls.is_ret_bysret(), + let (ret_ty, ret_attr) = x86_64_ty(rty, |cls| cls.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 cb47555063843..8fadb068b000d 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -319,9 +319,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 02f276cd0503c..3532273075602 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -907,9 +907,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 a78be9c8b2b1d..4c6e8740aec24 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 74ec46ccfcd47..845152f855251 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -400,7 +400,8 @@ impl Integer for $T { #[inline] 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 52f620f97ce86..0dabe7fafa834 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -237,7 +237,8 @@ impl Integer for $T { #[inline] 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 ea4a9059e729e..8a6c05ce6e2ae 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 6f4f1a34977e9..e8dad2fc5e862 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 55861f127bb44..fb0415f200022 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -343,7 +343,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; @@ -359,7 +361,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 801a4af281ec3..15a7472808432 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -473,6 +473,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 */ @@ -631,6 +656,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; @@ -737,7 +804,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 95fc53c1b55e0..da3dc6b2a2e5a 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -636,7 +636,9 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { let child_data = Cell::new((notify_chan, child_arc, ancestors)); let result: ~fn() = || { // Agh. Get move-mode items into the closure. FIXME (#2829) - let mut (notify_chan, child_arc, ancestors) = child_data.take(); + let (notify_chan, 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 ea0e212b14f79..dcd02744cf902 100644 --- a/src/libstd/to_str.rs +++ b/src/libstd/to_str.rs @@ -53,8 +53,9 @@ impl ToStr for (A,) { impl ToStr for HashMap { #[inline] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"{", true); - for self.iter().advance |(key, value)| { + let mut acc = ~"{"; + let mut first = true; + for self.iter().advance |key, value| { if first { first = false; } @@ -73,7 +74,8 @@ impl ToStr for HashMap { impl ToStr for HashSet { #[inline] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"{", true); + let mut acc = ~"{"; + let mut first = true; for self.iter().advance |element| { if first { first = false; @@ -121,7 +123,8 @@ impl ToStr for (A, B, C) { impl<'self,A:ToStr> ToStr for &'self [A] { #[inline] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"[", true); + let mut acc = ~"["; + let mut first = true; for self.iter().advance |elt| { if first { first = false; @@ -139,7 +142,8 @@ impl<'self,A:ToStr> ToStr for &'self [A] { impl ToStr for ~[A] { #[inline] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"[", true); + let mut acc = ~"["; + let mut first = true; for self.iter().advance |elt| { if first { first = false; @@ -157,7 +161,8 @@ impl ToStr for ~[A] { impl ToStr for @[A] { #[inline] fn to_str(&self) -> ~str { - let mut (acc, first) = (~"[", true); + let mut acc = ~"["; + let mut first = true; for self.iter().advance |elt| { if first { first = false; diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 56e6bacf93e30..3649709b73e41 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) @@ -1209,7 +1210,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 v.iter().advance |p| { let (t, u) = copy *p; ts.push(t); @@ -1227,7 +1229,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 9ba7cb3c818ea..4ffaba0906102 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -619,6 +619,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 32508f3b477a1..383faf22037d7 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -62,6 +62,7 @@ pub enum ObsoleteSyntax { ObsoleteFixedLengthVectorType, ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl, + ObsoleteMutWithMultipleBindings, } impl to_bytes::IterBytes for ObsoleteSyntax { @@ -223,6 +224,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 d67771fc43547..11c73fe57111e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -83,7 +83,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}; @@ -821,6 +822,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 { @@ -2560,6 +2566,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, @@ -4420,7 +4431,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 00d73b02dbc6e..07adc3d81e5f3 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 drop(&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 38983a9aca6a0..99057ba940c56 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 does not fulfill `Owned` - let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned` - let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned` + let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send` + let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send` + let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send` } diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs index 605e59d56c893..5f0d4bc60ac01 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 does not fulfill `Owned` + let y = x.take(); //~ ERROR does not fulfill `Send` 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 d3cc39d38b692d43c04d27a898ee291799b15ce9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 7 Jun 2013 15:47:05 -0700 Subject: [PATCH 06/18] libsyntax: Fix merge fallout --- src/libsyntax/parse/parser.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 11c73fe57111e..5981e39abb74a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -84,8 +84,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; From 110813e7b409413c238616705f0e68b8bc46d675 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 7 Jun 2013 19:59:32 -0700 Subject: [PATCH 07/18] 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 83c1a3c80db24..a90089bb47035 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -610,12 +610,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]) -> ValueRef { From 511a845d5f248c5306f09e1f2ba88883414f4859 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 10 Jun 2013 15:55:51 -0700 Subject: [PATCH 08/18] 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 15a7472808432..1618faf81b255 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -357,7 +357,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] { @@ -685,7 +686,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 5793b6c945f5c96ebaee2f1a53d952e296aef553 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 10 Jun 2013 19:42:28 -0700 Subject: [PATCH 09/18] 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 383faf22037d7..7f2d06ee1e41f 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -63,6 +63,7 @@ pub enum ObsoleteSyntax { ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl, ObsoleteMutWithMultipleBindings, + ObsoletePatternCopyKeyword, } impl to_bytes::IterBytes for ObsoleteSyntax { @@ -229,6 +230,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 5981e39abb74a..ee5ef8dfa6b9e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -84,6 +84,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}; @@ -2445,8 +2446,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 afebb48fc29bc2a2a23e016b9d07a91dae60e203 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 11 Jun 2013 19:13:42 -0700 Subject: [PATCH 10/18] 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 | 18 +++--- 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/time.rs | 2 +- src/librustc/back/link.rs | 30 +++++----- 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/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/librusti/rusti.rs | 3 +- src/libstd/hash.rs | 7 ++- src/libstd/num/num.rs | 2 +- src/libstd/path.rs | 16 ++++-- src/libsyntax/diagnostic.rs | 27 ++++++--- 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 | 2 +- src/test/run-pass/vec-growth.rs | 8 +-- src/test/run-pass/while-prelude-drop.rs | 2 +- 57 files changed, 316 insertions(+), 209 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 0701d61351cea..e7b24603b66e7 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 3e2f484ee53d4..3de55945ddf04 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -226,8 +226,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}; } } @@ -582,8 +582,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 604d9ba73732a..79e09c32030b3 100644 --- a/src/libextra/arena.rs +++ b/src/libextra/arena.rs @@ -186,20 +186,18 @@ impl Arena { #[inline] 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) } } @@ -237,7 +235,7 @@ impl Arena { let after_tydesc = head.fill + sys::size_of::<*TyDesc>(); 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::<*TyDesc>()); @@ -245,7 +243,7 @@ impl Arena { //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)); } } diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs index 6e4507d4277ab..4fe7761bf18da 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 9c416550eb787..fa064e6330e7b 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 15553b035f65e..a71be18174ab8 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -60,25 +60,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 f9eaa2bf02ddf..a60f51e751e1c 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -93,10 +93,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)); } } } @@ -192,7 +192,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)) } } @@ -218,7 +218,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 08da4abf3fa4f..0dc966771480a 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -511,11 +511,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/time.rs b/src/libextra/time.rs index 555563a0cd7e3..931a42d3c5377 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -849,7 +849,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 01ad3507b83ea..ba9caf143c8b2 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -640,15 +640,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 ':' @@ -684,12 +684,14 @@ pub fn mangle(sess: Session, ss: path) -> ~str { let mut n = ~"_ZN"; // Begin name-sequence. for ss.iter().advance |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/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index b96e96c9618fb..f8ecef3b4a49c 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -979,7 +979,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.iter().advance |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 ba19e7e6eb2b7..b0cc52dcfe530 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 e06fd8f971791..e4a866c5df419 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -2091,8 +2091,12 @@ impl Resolver { let mut first = true; let mut result = ~""; for idents.iter().advance |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 3c263b1c01eb6..76d6d390bd793 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -95,15 +95,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 a90089bb47035..e48a98cd90c0f 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -68,13 +68,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 79d83fbc85703..c1840abf4fdd2 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -970,9 +970,12 @@ pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str { for p.iter().advance |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/ty.rs b/src/librustc/middle/ty.rs index 984bc8236a7a3..fb50848dc0ad8 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) } @@ -2205,10 +2205,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 97e0cd4baf844..1da76644244fa 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -213,6 +213,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 ca167c3726ae2..e9deef6b22364 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.iter().enumerate().advance |(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 584e6ccc88730..35a433ec9dedd 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/librusti/rusti.rs b/src/librusti/rusti.rs index 54a404d971eec..3efe90555792a 100644 --- a/src/librusti/rusti.rs +++ b/src/librusti/rusti.rs @@ -402,7 +402,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 8e88bfb463291..6c3fcd41ed3b9 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -24,6 +24,7 @@ use container::Container; use iterator::IteratorUtil; use rt::io::Writer; +use str::OwnedStr; use to_bytes::IterBytes; use uint; use vec::ImmutableVector; @@ -369,7 +370,7 @@ impl Streaming for SipState { let r = self.result_bytes(); let mut s = ~""; for r.iter().advance |b| { - s += uint::to_str_radix(*b as uint, 16u); + s.push_str(uint::to_str_radix(*b as uint, 16u)); } s } @@ -471,7 +472,7 @@ mod tests { fn to_hex_str(r: &[u8, ..8]) -> ~str { let mut s = ~""; for r.iter().advance |b| { - s += uint::to_str_radix(*b as uint, 16u); + s.push_str(uint::to_str_radix(*b as uint, 16u)); } s } @@ -492,7 +493,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 30a18a0587bc0..b856c3c65ea5a 100644 --- a/src/libstd/num/num.rs +++ b/src/libstd/num/num.rs @@ -412,7 +412,7 @@ pub fn pow_with_uint+Mul>(radix: uint, pow if my_pow % 2u == 1u { total = total * multiplier; } - my_pow = my_pow / 2u; + my_pow = my_pow / 2u; multiplier = multiplier * multiplier; } total diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 700bfff3f5d79..ff0821bb9a0be 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 vec::{OwnedVector, ImmutableVector}; @@ -467,7 +467,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("/") } @@ -646,15 +646,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 89867922b25bd..7bd037236e900 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -264,8 +264,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); } @@ -286,23 +289,29 @@ 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- - _ => " " // -squiggly-line as well (instead of a - }; // space). This way the squiggly-line will - } // usually appear in the correct position. + // Whenever a tab occurs on the previous line, we insert one on + // the error-point-squiggly-line as well (instead of a space). + // That way the squiggly line will usually appear in the correct + // position. + match curChar { + '\t' => s.push_char('\t'), + _ => s.push_char(' '), + }; + } io::stderr().write_str(s); let mut s = ~"^"; let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { // the ^ already takes up one space let num_squigglies = hi.col.to_uint()-lo.col.to_uint()-1u; - for num_squigglies.times() { s += "~"; } + for num_squigglies.times() { + s.push_char('~') + } } print_maybe_colored(s + "\n", diagnosticcolor(lvl)); } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 80ab54b7e2cfe..7df8874076e09 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -26,8 +26,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 2c5ec0909d951..8e1276d52d1d6 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -65,8 +65,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) { @@ -76,13 +76,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) { @@ -92,23 +94,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()); @@ -155,19 +156,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()); @@ -433,10 +434,10 @@ impl gen_init for protocol { let mut server_states = ~[]; for (copy self.states).iter().advance |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 2baf08b68f1c6..01af33b13b856 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -254,7 +254,7 @@ fn read_block_comment(rdr: @mut StringReader, bump(rdr); } if !is_eof(rdr) { - curr_line += "*/"; + curr_line.push_str("*/"); bump(rdr); bump(rdr); } @@ -278,13 +278,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 cde4c754d560e..e003e2b27e9a2 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -192,10 +192,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 2092f0fa5facd..4a87283295266 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -180,7 +180,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); @@ -448,8 +448,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 { @@ -461,7 +461,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 ee5ef8dfa6b9e..a7c46d609cae2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4257,8 +4257,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 df599596d7d00..18e6c1817991b 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -178,14 +178,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 4e03d9bac7040..7cd3faf9a9053 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -122,12 +122,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 4b5880de8a52e..80990063431a0 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 96c7e4e9b375b..49a3a3ec5d7d3 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 set.iter().advance |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 f3efcc21ea9bd..da8d65a1dcbab 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -47,7 +47,7 @@ fn make_cumulative(aa: ~[AminoAcids]) -> ~[AminoAcids] { let mut ans: ~[AminoAcids] = ~[]; for aa.iter().advance |a| { cp += a.prob; - ans += [AminoAcids {ch: a.ch, prob: cp}]; + ans.push(AminoAcids {ch: a.ch, prob: cp}); } ans } diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 20042aa0e918a..7b850e05b405b 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 f66de3853743a..2396d6efc5cc1 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -103,7 +103,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 f7b9371df5731..b5a5eed6a35a2 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.iter().advance |elt| { r += f(*elt); } + for self.iter().advance |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 3f3cf5e5aaa0e..fe06c973dbfd8 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.iter().advance |elt| { r += f(elt); } + for self.iter().advance |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 85575b2ea8bb6..d0c58b50e2cec 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.iter().advance |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 421cd1d4d0bb3..0ddc39d6b18cc 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.iter().advance |x| { f(x); } } fn map_(&self, f: &fn(&T) -> U) -> ~[U] { let mut r = ~[]; - for self.iter().advance |elt| { r += ~[f(elt)]; } + for self.iter().advance |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 dc6bdbf5c1a5c..5952afa6676b7 100644 --- a/src/test/run-pass/trait-generic.rs +++ b/src/test/run-pass/trait-generic.rs @@ -33,7 +33,7 @@ impl map for ~[T] { let mut r = ~[]; // FIXME: #7355 generates bad code with Iterator for std::uint::range(0, self.len()) |i| { - r += ~[f(&self[i])]; + r.push(f(&self[i])); } 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 7b2ede97ea33ede9da3916efe547ecbee8c612df Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 14 Jun 2013 18:21:47 -0700 Subject: [PATCH 11/18] 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 | 8 +- src/libextra/test.rs | 248 ++++++------ src/librustc/driver/driver.rs | 18 +- src/librustc/metadata/encoder.rs | 75 ++-- src/librustc/metadata/tyencode.rs | 1 - src/librustc/middle/astencode.rs | 31 +- src/librustc/middle/reachable.rs | 414 ++++++++++++++++++++ src/librustc/middle/resolve.rs | 249 +++++------- src/librustc/middle/trans/base.rs | 14 +- src/librustc/middle/trans/callee.rs | 2 +- src/librustc/middle/trans/common.rs | 79 +++- src/librustc/middle/trans/mod.rs | 1 - src/librustc/middle/trans/reachable.rs | 246 ------------ 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.rs | 1 + src/librustpkg/rustpkg.rs | 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, 1314 insertions(+), 944 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 f5db15c6059da..9270fa75a2e06 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -153,7 +153,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 { @@ -456,7 +456,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 { @@ -559,7 +561,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 72e70943ce1cc..61c23f9b4714d 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -19,15 +19,21 @@ 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::task; use core::to_str::ToStr; +use core::u64; use core::uint; use core::vec; @@ -609,152 +615,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 2229a85836aa2..18693b52fc87e 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; @@ -299,10 +299,16 @@ 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)); - if phases.to == cu_no_trans { return (Some(crate), Some(ty_cx)); } + if phases.to == cu_no_trans { + return (Some(crate), Some(ty_cx)); + } let maps = astencode::Maps { root_map: root_map, @@ -315,9 +321,13 @@ pub fn compile_rest(sess: Session, 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 f8ecef3b4a49c..b1967752e45c8 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; @@ -60,7 +59,6 @@ pub type encode_inlined_item<'self> = &'self fn(ecx: &EncodeContext, pub struct EncodeParams<'self> { diag: @span_handler, tcx: ty::ctxt, - reachable: reachable::map, reexports2: middle::resolve::ExportMap2, item_symbols: &'self HashMap, discrim_symbols: &'self HashMap, @@ -87,7 +85,6 @@ pub struct EncodeContext<'self> { diag: @span_handler, tcx: ty::ctxt, stats: @mut Stats, - reachable: reachable::map, reexports2: middle::resolve::ExportMap2, item_symbols: &'self HashMap, discrim_symbols: &'self HashMap, @@ -157,8 +154,8 @@ fn encode_trait_ref(ebml_w: &mut writer::Encoder, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| r.contains(&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); @@ -185,8 +182,8 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| r.contains(&a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs) + }; for params.iter().advance |param| { ebml_w.start_tag(tag); tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param); @@ -218,8 +215,8 @@ pub fn write_type(ecx: &EncodeContext, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| r.contains(&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); } @@ -231,8 +228,8 @@ pub fn write_vstore(ecx: &EncodeContext, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| r.contains(&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); } @@ -264,8 +261,8 @@ fn encode_method_fty(ecx: &EncodeContext, diag: ecx.diag, ds: def_to_str, tcx: ecx.tcx, - reachable: |a| r.contains(&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(); @@ -780,13 +777,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_static(*) => true, - _ => false - }; - if !must_write && !reachable(ecx, item.id) { return; } fn add_to_index_(item: @item, ebml_w: &writer::Encoder, index: @mut ~[entry]) { @@ -898,23 +888,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)); @@ -944,6 +917,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(); @@ -1092,7 +1082,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); @@ -1162,6 +1151,12 @@ fn encode_info_for_items(ecx: &EncodeContext, visit::visit_foreign_item(ni, (cx, v)); match 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; // See above let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) }; @@ -1466,7 +1461,7 @@ 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 type_abbrevs = @mut HashMap::new(); @@ -1475,7 +1470,6 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { diag: diag, tcx: tcx, stats: stats, - reachable: reachable, reexports2: reexports2, item_symbols: item_symbols, discrim_symbols: discrim_symbols, @@ -1557,7 +1551,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 0f9937fd3c0cf..fb72617b743fc 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 fb8238b84d6e6..70e94844319e7 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -368,14 +368,17 @@ impl tr for ast::def { ast::def_static_method(did.tr(xcx), did2_opt.map(|did2| did2.tr(xcx)), p) - }, - 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)), - ast::def_foreign_mod(did) => ast::def_foreign_mod(did.tr(xcx)), - ast::def_static(did, m) => ast::def_static(did.tr(xcx), m), - ast::def_arg(nid, b) => ast::def_arg(xcx.tr_id(nid), b), - ast::def_local(nid, b) => ast::def_local(xcx.tr_id(nid), b), + } + 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)) } + ast::def_foreign_mod(did) => { ast::def_foreign_mod(did.tr(xcx)) } + ast::def_static(did, m) => { ast::def_static(did.tr(xcx), m) } + ast::def_arg(nid, b) => { ast::def_arg(xcx.tr_id(nid), b) } + ast::def_local(nid, b) => { ast::def_local(xcx.tr_id(nid), b) } ast::def_variant(e_did, v_did) => { ast::def_variant(e_did.tr(xcx), v_did.tr(xcx)) }, @@ -692,12 +695,12 @@ trait get_ty_str_ctxt { impl<'self> get_ty_str_ctxt for e::EncodeContext<'self> { fn ty_str_ctxt(&self) -> @tyencode::ctxt { - let r = self.reachable; - @tyencode::ctxt {diag: self.tcx.sess.diagnostic(), - ds: e::def_to_str, - tcx: self.tcx, - reachable: |a| r.contains(&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/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 e4a866c5df419..cffb7e75e3945 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -652,21 +652,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, } } } @@ -1230,49 +1218,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.iter().advance |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 @@ -1283,8 +1251,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, @@ -1292,30 +1260,36 @@ impl Resolver { ImplModuleKind, sp); - ModuleReducedGraphParent(name_bindings.get_module()) + ModuleReducedGraphParent( + name_bindings.get_module()) } }; - // For each static method... + // For each method... for methods.iter().advance |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); } } _ => {} @@ -1324,41 +1298,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).iter().advance |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(); @@ -1366,35 +1322,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); } } } @@ -1751,6 +1706,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(*) | @@ -2391,7 +2349,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; @@ -3269,22 +3228,8 @@ impl Resolver { pub fn add_exports_for_module(@mut self, exports2: &mut ~[Export2], module_: @mut Module) { - for module_.children.iter().advance |(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.iter().advance |(ident, importresolution)| { + for module_.import_resolutions.iter().advance |ident, + importresolution| { if importresolution.privacy != Public { debug!("(computing exports) not reexporting private `%s`", self.session.str_of(*ident)); @@ -4518,8 +4463,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 { @@ -4947,6 +4892,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 => { @@ -5415,7 +5376,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 a0628bc8e87c4..2553de08b60e0 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -54,7 +54,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::tvec; use middle::trans::type_of; use middle::trans::type_of::*; @@ -2447,7 +2446,6 @@ pub fn get_item_val(ccx: @mut 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) => { @@ -2521,7 +2519,7 @@ pub fn get_item_val(ccx: @mut 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); @@ -2897,16 +2895,12 @@ pub fn trans_crate(sess: session::Session, tcx: ty::ctxt, output: &Path, emap2: resolve::ExportMap2, - maps: astencode::Maps) -> (ContextRef, ModuleRef, LinkMeta) { + reachable_map: @mut HashSet, + maps: astencode::Maps) + -> (ContextRef, ModuleRef, LinkMeta) { let mut symbol_hasher = hash::default_state(); let link_meta = link::build_link_meta(sess, crate, output, &mut symbol_hasher); - let reachable = reachable::find_reachable( - &crate.node.module, - emap2, - tcx, - maps.method_map - ); // Append ".rc" to crate name as LLVM module identifier. // diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 8fadb068b000d..cead0d43dca0c 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -146,7 +146,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee { ast::def_static(*) | 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 c1840abf4fdd2..2c738fd501435 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -123,7 +123,84 @@ pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res { } } -pub type ExternMap = HashMap<@str, ValueRef>; +pub type ExternMap = @mut HashMap<@str, ValueRef>; + +// Crate context. Every crate we compile has one of these. +pub struct CrateContext { + sess: session::Session, + llmod: ModuleRef, + td: TargetData, + tn: @TypeNames, + externs: ExternMap, + intrinsics: HashMap<&'static str, ValueRef>, + item_vals: @mut HashMap, + exp_map2: resolve::ExportMap2, + item_symbols: @mut HashMap, + link_meta: LinkMeta, + enum_sizes: @mut HashMap, + discrims: @mut HashMap, + discrim_symbols: @mut HashMap, + tydescs: @mut HashMap, + // Set when running emit_tydescs to enforce that no more tydescs are + // created. + finished_tydescs: @mut bool, + // Track mapping of external ids to local items imported for inlining + external: @mut HashMap>, + // Cache instances of monomorphized functions + monomorphized: @mut HashMap, + monomorphizing: @mut HashMap, + // Cache computed type parameter uses (see type_use.rs) + type_use_cache: @mut HashMap, + // Cache generated vtables + vtables: @mut HashMap, + // Cache of constant strings, + const_cstr_cache: @mut HashMap<@str, ValueRef>, + + // Reverse-direction for const ptrs cast from globals. + // Key is an int, cast from a ValueRef holding a *T, + // Val is a ValueRef holding a *[T]. + // + // Needed because LLVM loses pointer->pointee association + // when we ptrcast, and we have to ptrcast during translation + // of a [T] const because we form a slice, a [*T,int] pair, not + // a pointer to an LLVM array type. + const_globals: @mut HashMap, + + // Cache of emitted const values + const_values: @mut HashMap, + + // Cache of external const values + extern_const_values: @mut HashMap, + + module_data: @mut HashMap<~str, ValueRef>, + lltypes: @mut HashMap, + llsizingtypes: @mut HashMap, + adt_reprs: @mut HashMap, + names: namegen, + next_addrspace: addrspace_gen, + symbol_hasher: @mut hash::State, + type_hashcodes: @mut HashMap, + type_short_names: @mut HashMap, + all_llvm_symbols: @mut HashSet<@str>, + tcx: ty::ctxt, + maps: astencode::Maps, + stats: @mut Stats, + upcalls: @upcall::Upcalls, + tydesc_type: TypeRef, + int_type: TypeRef, + float_type: TypeRef, + opaque_vec_type: TypeRef, + builder: BuilderRef_res, + shape_cx: shape::Ctxt, + crate_map: ValueRef, + // Set when at least one function uses GC. Needed so that + // decl_gc_metadata knows whether to link to the module metadata, which + // 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, + reachable_map: @mut HashSet, +} // Types used for llself. pub struct ValSelfData { diff --git a/src/librustc/middle/trans/mod.rs b/src/librustc/middle/trans/mod.rs index c2a25d80998a5..64d6bbec87c48 100644 --- a/src/librustc/middle/trans/mod.rs +++ b/src/librustc/middle/trans/mod.rs @@ -37,7 +37,6 @@ pub mod foreign; pub mod reflect; pub mod debuginfo; pub mod type_use; -pub mod reachable; pub mod machine; pub mod adt; pub mod asm; diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs deleted file mode 100644 index e950c24c49e8d..0000000000000 --- a/src/librustc/middle/trans/reachable.rs +++ /dev/null @@ -1,246 +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 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).iter().advance |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.iter().advance |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.iter().advance |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.iter().advance |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_static(*) | - 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, _bounds, 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.iter().advance |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 1da76644244fa..b4a710e15b885 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -791,10 +791,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 94520b6faca65..5065a475a4055 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -81,10 +81,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 884f72b57f081..7a4ea0999efab 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 658fd67ee5855..ed19310d5d69e 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 4462d43015cfc..eb912aa2dda4b 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 371d389f712c7..a185633a7ac77 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! @@ -102,11 +125,12 @@ impl InferCtxt { vb.vals.insert(vid.to_uint(), new_v); } - 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 @@ -155,14 +179,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 @@ -194,13 +235,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.rs b/src/librustc/rustc.rs index a27838b5d11e3..957cf02ed77ec 100644 --- a/src/librustc/rustc.rs +++ b/src/librustc/rustc.rs @@ -80,6 +80,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.rs b/src/librustpkg/rustpkg.rs index d70428e733858..ca13ba39d59c4 100644 --- a/src/librustpkg/rustpkg.rs +++ b/src/librustpkg/rustpkg.rs @@ -185,7 +185,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 ff0821bb9a0be..990780e5dc26c 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -335,8 +335,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| { @@ -349,12 +349,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, } @@ -387,7 +410,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, @@ -419,9 +442,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, @@ -434,7 +472,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 1618faf81b255..126e471d42917 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -859,7 +859,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 265e9e444e94a..8e1c51caf7c1a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -205,7 +205,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 4ffaba0906102..6761736d2f374 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -59,7 +59,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_static(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 e003e2b27e9a2..04f62f3574903 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -51,251 +51,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 7f2d06ee1e41f..fff4c125af620 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -73,7 +73,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 a7c46d609cae2..64bdfd4a4d332 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -64,7 +64,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; @@ -84,7 +84,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}; @@ -274,6 +274,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 b8cc4d686d0bd11f295f8c8e269ed876f6e64eb8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 14 Jun 2013 19:40:11 -0700 Subject: [PATCH 12/18] librustc: Fix merge fallout. --- src/librustc/metadata/encoder.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/libstd/path.rs | 2 +- src/libstd/str.rs | 6 ++++-- src/libsyntax/ext/pipes/pipec.rs | 2 +- src/libsyntax/parse/parser.rs | 2 +- 12 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index b1967752e45c8..5ff52b1859ad3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1155,7 +1155,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; // See above 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 cffb7e75e3945..778d6e1f68550 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1299,7 +1299,7 @@ impl Resolver { } item_impl(_, Some(_), ty, ref methods) => { - visit_item(item, parent, visitor); + visit_item(item, (parent, visitor)); } item_trait(_, _, ref methods) => { @@ -1349,7 +1349,7 @@ impl Resolver { match ty_m.explicit_self.node { sty_static => {} _ => { - method_names.insert(ident); + method_names.insert(ident, ()); } } } @@ -2054,7 +2054,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 76d6d390bd793..81a69dfca248c 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -95,7 +95,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 2553de08b60e0..479f0cd71186a 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2897,7 +2897,7 @@ pub fn trans_crate(sess: session::Session, emap2: resolve::ExportMap2, reachable_map: @mut HashSet, maps: astencode::Maps) - -> (ContextRef, ModuleRef, LinkMeta) { + -> (ModuleRef, LinkMeta) { let mut symbol_hasher = hash::default_state(); let link_meta = link::build_link_meta(sess, crate, output, &mut symbol_hasher); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 2c738fd501435..3e583e3aa25f4 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1052,7 +1052,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 b4a710e15b885..d224d182950d3 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -799,9 +799,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())); } } } @@ -1141,7 +1140,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 69d4d82d15f28..df81ebd48aa23 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -230,7 +230,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); @@ -520,8 +520,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); @@ -576,8 +575,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); @@ -808,7 +806,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); @@ -842,8 +840,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); @@ -970,7 +967,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); @@ -1034,7 +1031,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); @@ -1086,7 +1083,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/libstd/path.rs b/src/libstd/path.rs index 990780e5dc26c..7b5fc62c18acc 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 126e471d42917..ae2af203ca6d4 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1427,7 +1427,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; @@ -1575,7 +1576,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 8e1276d52d1d6..3044cd50b344c 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -98,7 +98,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 64bdfd4a4d332..f1b5c4d16be97 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -378,7 +378,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 2d98b43da2cf57bc1c43ecca22dc434288fa4c35 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 18 Jun 2013 09:39:16 -0700 Subject: [PATCH 13/18] Rewrite each_path to allow performance improvements in the future. Instead of determining paths from the path tag, we iterate through modules' children recursively in the metadata. This will allow for lazy external module resolution. --- src/libextra/sync.rs | 2 +- src/librustc/metadata/common.rs | 4 + src/librustc/metadata/csearch.rs | 16 +- src/librustc/metadata/decoder.rs | 323 +++++++++++++++++------- src/librustc/metadata/encoder.rs | 200 ++++++++++++--- src/librustc/middle/reachable.rs | 69 +++-- src/librustc/middle/resolve.rs | 22 +- src/librustc/middle/trans/base.rs | 21 +- src/librustc/middle/trans/common.rs | 79 +----- src/librustc/middle/trans/context.rs | 16 +- src/librustc/middle/typeck/check/mod.rs | 2 + src/librustc/middle/typeck/coherence.rs | 150 +++++------ src/libstd/char.rs | 1 + src/libstd/os.rs | 6 +- src/libstd/rand.rs | 1 + src/libstd/str.rs | 21 +- src/libstd/unstable/extfmt.rs | 1 + 17 files changed, 574 insertions(+), 360 deletions(-) diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs index 9270fa75a2e06..c00da2eb95b90 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -381,7 +381,7 @@ impl Sem<~[Waitqueue]> { // The only other places that condvars get built are rwlock.write_cond() // and rwlock_write_mode. pub fn access_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { - do self.access { + do self.access_waitqueue { blk(&Condvar { sem: self, order: Nothing }) } } diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index f487c73372fad..e7725436f2b4f 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -176,6 +176,10 @@ pub static tag_item_method_tps: uint = 0x7b; pub static tag_item_method_fty: uint = 0x7c; pub static tag_item_method_transformed_self_ty: uint = 0x7d; +pub static tag_mod_child: uint = 0x7e; +pub static tag_misc_info: uint = 0x7f; +pub static tag_misc_info_crate_items: uint = 0x80; + pub struct LinkMeta { name: @str, vers: @str, diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index bfc5d512b3702..4ede9f96f1f40 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -97,18 +97,14 @@ pub fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id) return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx) } -pub fn get_impls_for_mod(cstore: @mut cstore::CStore, def: ast::def_id, - name: Option) - -> @~[@resolve::Impl] { - let cdata = cstore::get_crate_data(cstore, def.crate); - do decoder::get_impls_for_mod(cstore.intr, cdata, def.node, name) |cnum| { - cstore::get_crate_data(cstore, cnum) - } +/// Returns information about the given implementation. +pub fn get_impl(cstore: @mut cstore::CStore, impl_def_id: ast::def_id) + -> resolve::Impl { + let cdata = cstore::get_crate_data(cstore, impl_def_id.crate); + decoder::get_impl(cstore.intr, cdata, impl_def_id.node) } -pub fn get_method(tcx: ty::ctxt, - def: ast::def_id) -> ty::Method -{ +pub fn get_method(tcx: ty::ctxt, def: ast::def_id) -> ty::Method { let cdata = cstore::get_crate_data(tcx.cstore, def.crate); decoder::get_method(tcx.cstore.intr, cdata, def.node, tcx) } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 30f0a52b4e54b..263c88017afd9 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -458,64 +458,192 @@ pub fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) -> bool { return true; } -/// Iterates over all the paths in the given crate. -pub fn each_path(intr: @ident_interner, - cdata: cmd, - get_crate_data: GetCrateDataCb, - f: &fn(&str, def_like, ast::visibility) -> bool) - -> bool { - // FIXME #4572: This function needs to be nuked, as it's impossible to make fast. - // It's the source of most of the performance problems when compiling small crates. +struct EachItemContext<'self> { + intr: @ident_interner, + cdata: cmd, + get_crate_data: GetCrateDataCb<'self>, + path_builder: &'self mut ~str, + callback: &'self fn(&str, def_like, ast::visibility) -> bool, +} - let root = reader::Doc(cdata.data); - let items = reader::get_doc(root, tag_items); - let items_data = reader::get_doc(items, tag_items_data); - - // First, go through all the explicit items. - for reader::tagged_docs(items_data, tag_items_data_item) |item_doc| { - let path = ast_map::path_to_str(item_path(item_doc), intr); - let path_is_empty = path.is_empty(); - if !path_is_empty { - // Extract the def ID. - let def_id = item_def_id(item_doc, cdata); - - // Construct the def for this item. - debug!("(each_path) yielding explicit item: %s", path); - let def_like = item_to_def_like(item_doc, def_id, cdata.cnum); - - let vis = item_visibility(item_doc); - - // Hand the information off to the iteratee. - if !f(path, def_like, vis) { - return false; +impl<'self> EachItemContext<'self> { + // Pushes the given name and returns the old length. + fn push_name(&mut self, string: &str) -> uint { + let path_len = self.path_builder.len(); + if path_len != 0 { + self.path_builder.push_str("::") + } + self.path_builder.push_str(string); + path_len + } + + // Pops the given name. + fn pop_name(&mut self, old_len: uint) { + // XXX(pcwalton): There's no safe function to do this. :( + unsafe { + str::raw::set_len(self.path_builder, old_len) + } + } + + fn process_item_and_pop_name(&mut self, + doc: ebml::Doc, + def_id: ast::def_id, + old_len: uint) + -> bool { + let def_like = item_to_def_like(doc, def_id, self.cdata.cnum); + match def_like { + dl_def(def) => { + debug!("(iterating over each item of a module) processing \ + `%s` (def %?)", + *self.path_builder, + def); + } + _ => { + debug!("(iterating over each item of a module) processing \ + `%s` (%d:%d)", + *self.path_builder, + def_id.crate, + def_id.node); } } - // If this is a module, find the reexports. - for each_reexport(item_doc) |reexport_doc| { - let def_id_doc = - reader::get_doc(reexport_doc, - tag_items_data_item_reexport_def_id); - let def_id = reader::with_doc_data(def_id_doc, parse_def_id); - let def_id = translate_def_id(cdata, def_id); - - let reexport_name_doc = - reader::get_doc(reexport_doc, - tag_items_data_item_reexport_name); - let reexport_name = reexport_name_doc.as_str_slice(); - - let reexport_path; - if path_is_empty { - reexport_path = reexport_name.to_owned(); + let vis = item_visibility(doc); + + let mut continue = (self.callback)(*self.path_builder, def_like, vis); + + let family = item_family(doc); + if family == ForeignMod { + // These are unnamed; pop the name now. + self.pop_name(old_len) + } + + if continue { + // Recurse if necessary. + match family { + Mod | ForeignMod | Trait | Impl => { + continue = self.each_item_of_module(def_id); + } + Freeze | Struct | UnsafeFn | Fn | PureFn | ForeignFn | + UnsafeStaticMethod | StaticMethod | PureStaticMethod | Type | + ForeignType | Variant | Enum | PublicField | PrivateField | + InheritedField => {} + } + } + + if family != ForeignMod { + self.pop_name(old_len) + } + + continue + } + + fn each_item_of_module(&mut self, def_id: ast::def_id) -> bool { + // This item might not be in this crate. If it's not, look it up. + let (cdata, items) = if def_id.crate == self.cdata.cnum { + let items = reader::get_doc(reader::Doc(self.cdata.data), + tag_items); + (self.cdata, items) + } else { + let crate_data = (self.get_crate_data)(def_id.crate); + let root = reader::Doc(crate_data.data); + (crate_data, reader::get_doc(root, tag_items)) + }; + + // Look up the item. + let item_doc = match maybe_find_item(def_id.node, items) { + None => return false, + Some(item_doc) => item_doc, + }; + + self.each_child_of_module_or_crate(item_doc) + } + + fn each_child_of_module_or_crate(&mut self, item_doc: ebml::Doc) -> bool { + let mut continue = true; + + // Iterate over all children. + for reader::tagged_docs(item_doc, tag_mod_child) |child_info_doc| { + let child_def_id = reader::with_doc_data(child_info_doc, + parse_def_id); + let child_def_id = translate_def_id(self.cdata, child_def_id); + + // This item may be in yet another crate, if it was the child of + // a reexport. + let other_crates_items = if child_def_id.crate == + self.cdata.cnum { + reader::get_doc(reader::Doc(self.cdata.data), tag_items) } else { - reexport_path = path + "::" + reexport_name; + let crate_data = (self.get_crate_data)(child_def_id.crate); + let root = reader::Doc(crate_data.data); + reader::get_doc(root, tag_items) + }; + + debug!("(iterating over each item of a module) looking up item \ + %d:%d in `%s`, crate %d", + child_def_id.crate, + child_def_id.node, + *self.path_builder, + self.cdata.cnum); + + // Get the item. + match maybe_find_item(child_def_id.node, other_crates_items) { + None => {} + Some(child_item_doc) => { + // Push the name. + let child_name = item_name(self.intr, child_item_doc); + debug!("(iterating over each item of a module) pushing \ + name `%s` onto `%s`", + token::ident_to_str(&child_name), + *self.path_builder); + let old_len = + self.push_name(token::ident_to_str(&child_name)); + + // Process this item. + continue = self.process_item_and_pop_name(child_item_doc, + child_def_id, + old_len); + + if !continue { + break + } + } } + } + + if !continue { + return false + } - // This reexport may be in yet another crate - let other_crates_items = if def_id.crate == cdata.cnum { - items + // Iterate over reexports. + for each_reexport(item_doc) |reexport_doc| { + let def_id_doc = reader::get_doc( + reexport_doc, + tag_items_data_item_reexport_def_id); + let orig_def_id = reader::with_doc_data(def_id_doc, parse_def_id); + + // NB: was "cdata" + let def_id = translate_def_id(self.cdata, orig_def_id); + + let name_doc = reader::get_doc(reexport_doc, + tag_items_data_item_reexport_name); + let name = name_doc.as_str_slice(); + + // Push the name. + debug!("(iterating over each item of a module) pushing \ + reexported name `%s` onto `%s` (crate %d, orig %d, \ + in crate %d)", + name, + *self.path_builder, + def_id.crate, + orig_def_id.crate, + self.cdata.cnum); + let old_len = self.push_name(name); + + // This reexport may be in yet another crate. + let other_crates_items = if def_id.crate == self.cdata.cnum { + reader::get_doc(reader::Doc(self.cdata.data), tag_items) } else { - let crate_data = get_crate_data(def_id.crate); + let crate_data = (self.get_crate_data)(def_id.crate); let root = reader::Doc(crate_data.data); reader::get_doc(root, tag_items) }; @@ -523,29 +651,53 @@ pub fn each_path(intr: @ident_interner, // Get the item. match maybe_find_item(def_id.node, other_crates_items) { None => {} - Some(item_doc) => { - // Construct the def for this item. - let def_like = item_to_def_like(item_doc, - def_id, - cdata.cnum); - - // Hand the information off to the iteratee. - debug!("(each_path) yielding reexported \ - item: %s", reexport_path); - - if (!f(reexport_path, def_like, ast::public)) { - return false; - } + Some(reexported_item_doc) => { + continue = self.process_item_and_pop_name( + reexported_item_doc, + def_id, + old_len); } } + + if !continue { + break + } } + + continue } +} - return true; +/// Iterates over all the paths in the given crate. +pub fn each_path(intr: @ident_interner, + cdata: cmd, + get_crate_data: GetCrateDataCb, + f: &fn(&str, def_like, ast::visibility) -> bool) + -> bool { + // FIXME #4572: This function needs to be nuked, as it's impossible to + // make fast. It's the source of most of the performance problems when + // compiling small crates. + + let root_doc = reader::Doc(cdata.data); + let misc_info_doc = reader::get_doc(root_doc, tag_misc_info); + let crate_items_doc = reader::get_doc(misc_info_doc, + tag_misc_info_crate_items); + + let mut path_builder = ~""; + + let mut context = EachItemContext { + intr: intr, + cdata: cdata, + get_crate_data: get_crate_data, + path_builder: &mut path_builder, + callback: f, + }; + + // Iterate over all top-level crate items. + context.each_child_of_module_or_crate(crate_items_doc) } -pub fn get_item_path(cdata: cmd, id: ast::node_id) - -> ast_map::path { +pub fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path { item_path(lookup_item(id, cdata.data)) } @@ -661,35 +813,20 @@ fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc, rslt } -pub fn get_impls_for_mod(intr: @ident_interner, - cdata: cmd, - m_id: ast::node_id, - name: Option, - get_cdata: &fn(ast::crate_num) -> cmd) - -> @~[@resolve::Impl] { +/// Returns information about the given implementation. +pub fn get_impl(intr: @ident_interner, cdata: cmd, impl_id: ast::node_id) + -> resolve::Impl { let data = cdata.data; - let mod_item = lookup_item(m_id, data); - let mut result = ~[]; - for reader::tagged_docs(mod_item, tag_mod_impl) |doc| { - let did = reader::with_doc_data(doc, parse_def_id); - let local_did = translate_def_id(cdata, did); - debug!("(get impls for mod) getting did %? for '%?'", - local_did, name); - // The impl may be defined in a different crate. Ask the caller - // to give us the metadata - let impl_cdata = get_cdata(local_did.crate); - let impl_data = impl_cdata.data; - let item = lookup_item(local_did.node, impl_data); - let nm = item_name(intr, item); - if match name { Some(n) => { n == nm } None => { true } } { - let base_tps = item_ty_param_count(item); - result.push(@resolve::Impl { - did: local_did, ident: nm, - methods: item_impl_methods(intr, impl_cdata, item, base_tps) - }); - }; + let impl_item = lookup_item(impl_id, data); + let base_tps = item_ty_param_count(impl_item); + resolve::Impl { + did: ast::def_id { + crate: cdata.cnum, + node: impl_id, + }, + ident: item_name(intr, impl_item), + methods: item_impl_methods(intr, cdata, impl_item, base_tps), } - @result } pub fn get_method_name_and_explicit_self( diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 5ff52b1859ad3..187f2a99ed4c5 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -22,7 +22,7 @@ use middle; use util::ppaux::ty_to_str; use core::hash::HashUtil; -use core::hashmap::HashMap; +use core::hashmap::{HashMap, HashSet}; use core::int; use core::io; use core::str; @@ -64,7 +64,8 @@ pub struct EncodeParams<'self> { discrim_symbols: &'self HashMap, link_meta: &'self LinkMeta, cstore: @mut cstore::CStore, - encode_inlined_item: encode_inlined_item<'self> + encode_inlined_item: encode_inlined_item<'self>, + reachable: @mut HashSet, } struct Stats { @@ -73,6 +74,7 @@ struct Stats { dep_bytes: uint, lang_item_bytes: uint, link_args_bytes: uint, + misc_bytes: uint, item_bytes: uint, index_bytes: uint, zero_bytes: uint, @@ -91,7 +93,8 @@ pub struct EncodeContext<'self> { link_meta: &'self LinkMeta, cstore: &'self cstore::CStore, encode_inlined_item: encode_inlined_item<'self>, - type_abbrevs: abbrev_map + type_abbrevs: abbrev_map, + reachable: @mut HashSet, } pub fn reachable(ecx: &EncodeContext, id: node_id) -> bool { @@ -470,12 +473,77 @@ fn encode_reexported_static_methods(ecx: &EncodeContext, } } +/// Iterates through "auxiliary node IDs", which are node IDs that describe +/// top-level items that are sub-items of the given item. Specifically: +/// +/// * For enums, iterates through the node IDs of the variants. +/// +/// * For newtype structs, iterates through the node ID of the constructor. +fn each_auxiliary_node_id(item: @item, callback: &fn(node_id) -> bool) + -> bool { + let mut continue = true; + match item.node { + item_enum(ref enum_def, _) => { + for enum_def.variants.each |variant| { + continue = callback(variant.node.id); + if !continue { + break + } + } + } + item_struct(struct_def, _) => { + // If this is a newtype struct, return the constructor. + match struct_def.ctor_id { + Some(ctor_id) if struct_def.fields.len() > 0 && + struct_def.fields[0].node.kind == + ast::unnamed_field => { + continue = callback(ctor_id); + } + _ => {} + } + } + _ => {} + } + + continue +} + +fn encode_reexports(ecx: &EncodeContext, + ebml_w: &mut writer::Encoder, + id: node_id, + path: &[ast_map::path_elt]) { + debug!("(encoding info for module) encoding reexports for %d", id); + match ecx.reexports2.find(&id) { + Some(ref exports) => { + debug!("(encoding info for module) found reexports for %d", id); + for exports.each |exp| { + debug!("(encoding info for module) reexport '%s' for %d", + exp.name, id); + ebml_w.start_tag(tag_items_data_item_reexport); + ebml_w.start_tag(tag_items_data_item_reexport_def_id); + ebml_w.wr_str(def_to_str(exp.def_id)); + ebml_w.end_tag(); + ebml_w.start_tag(tag_items_data_item_reexport_name); + ebml_w.wr_str(exp.name); + ebml_w.end_tag(); + ebml_w.end_tag(); + encode_reexported_static_methods(ecx, ebml_w, path, exp); + } + } + None => { + debug!("(encoding info for module) found no reexports for %d", + id); + } + } +} + fn encode_info_for_mod(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, md: &_mod, id: node_id, path: &[ast_map::path_elt], - name: ident) { + name: ident, + vis: visibility) { ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(id)); encode_family(ebml_w, 'm'); @@ -484,6 +552,16 @@ fn encode_info_for_mod(ecx: &EncodeContext, // Encode info about all the module children. for md.items.iter().advance |item| { + ebml_w.start_tag(tag_mod_child); + ebml_w.wr_str(def_to_str(local_def(item.id))); + ebml_w.end_tag(); + + for each_auxiliary_node_id(*item) |auxiliary_node_id| { + ebml_w.start_tag(tag_mod_child); + ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id))); + ebml_w.end_tag(); + } + match item.node { item_impl(*) => { let (ident, did) = (item.ident, item.id); @@ -497,35 +575,16 @@ fn encode_info_for_mod(ecx: &EncodeContext, ebml_w.wr_str(def_to_str(local_def(did))); ebml_w.end_tag(); } - _ => {} // FIXME #4573: Encode these too. + _ => {} } } encode_path(ecx, ebml_w, path, ast_map::path_mod(name)); - // Encode the reexports of this module. - debug!("(encoding info for module) encoding reexports for %d", id); - match ecx.reexports2.find(&id) { - Some(ref exports) => { - debug!("(encoding info for module) found reexports for %d", id); - for exports.iter().advance |exp| { - debug!("(encoding info for module) reexport '%s' for %d", - exp.name, id); - ebml_w.start_tag(tag_items_data_item_reexport); - ebml_w.start_tag(tag_items_data_item_reexport_def_id); - ebml_w.wr_str(def_to_str(exp.def_id)); - ebml_w.end_tag(); - ebml_w.start_tag(tag_items_data_item_reexport_name); - ebml_w.wr_str(exp.name); - ebml_w.end_tag(); - ebml_w.end_tag(); - encode_reexported_static_methods(ecx, ebml_w, path, exp); - } - } - None => { - debug!("(encoding info for module) found no reexports for %d", - id); - } + // Encode the reexports of this module, if this module is public. + if vis == public { + debug!("(encoding info for module) encoding reexports for %d", id); + encode_reexports(ecx, ebml_w, id, path); } ebml_w.end_tag(); @@ -799,6 +858,7 @@ fn encode_info_for_item(ecx: &EncodeContext, } encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_symbol(ecx, ebml_w, item.id); + encode_name(ecx, ebml_w, item.ident); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item)); ebml_w.end_tag(); @@ -811,6 +871,7 @@ fn encode_info_for_item(ecx: &EncodeContext, let tps_len = generics.ty_params.len(); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); + encode_name(ecx, ebml_w, item.ident); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); encode_attributes(ebml_w, item.attrs); if tps_len > 0u || should_inline(item.attrs) { @@ -822,15 +883,29 @@ fn encode_info_for_item(ecx: &EncodeContext, } item_mod(ref m) => { add_to_index(); - encode_info_for_mod(ecx, ebml_w, m, item.id, path, item.ident); + encode_info_for_mod(ecx, + ebml_w, + m, + item.id, + path, + item.ident, + item.vis); } - item_foreign_mod(_) => { + item_foreign_mod(ref fm) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); encode_family(ebml_w, 'n'); encode_name(ecx, ebml_w, item.ident); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); + + // Encode all the items in this module. + for fm.items.each |foreign_item| { + ebml_w.start_tag(tag_mod_child); + ebml_w.wr_str(def_to_str(local_def(foreign_item.id))); + ebml_w.end_tag(); + } + ebml_w.end_tag(); } item_ty(_, ref generics) => { @@ -998,6 +1073,10 @@ fn encode_info_for_item(ecx: &EncodeContext, ebml_w.start_tag(tag_item_trait_method); encode_def_id(ebml_w, method_def_id); ebml_w.end_tag(); + + ebml_w.start_tag(tag_mod_child); + ebml_w.wr_str(def_to_str(method_def_id)); + ebml_w.end_tag(); } encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); for super_traits.iter().advance |ast_trait_ref| { @@ -1091,6 +1170,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, encode_family(ebml_w, purity_fn_family(purity)); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id)); + encode_name(ecx, ebml_w, nitem.ident); if abi.is_intrinsic() { (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_foreign(nitem)); } else { @@ -1107,6 +1187,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, } encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id)); encode_symbol(ecx, ebml_w, nitem.id); + encode_name(ecx, ebml_w, nitem.ident); encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident)); } } @@ -1120,9 +1201,13 @@ fn encode_info_for_items(ecx: &EncodeContext, let index = @mut ~[]; ebml_w.start_tag(tag_items_data); index.push(entry { val: crate_node_id, pos: ebml_w.writer.tell() }); - encode_info_for_mod(ecx, ebml_w, &crate.node.module, - crate_node_id, [], - syntax::parse::token::special_idents::invalid); + encode_info_for_mod(ecx, + ebml_w, + &crate.node.module, + crate_node_id, + [], + syntax::parse::token::special_idents::invalid, + public); let items = ecx.tcx.items; // See comment in `encode_side_tables_for_ii` in astencode @@ -1416,6 +1501,30 @@ fn encode_link_args(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { ebml_w.end_tag(); } +fn encode_misc_info(ecx: &EncodeContext, + crate: &crate, + ebml_w: &mut writer::Encoder) { + ebml_w.start_tag(tag_misc_info); + ebml_w.start_tag(tag_misc_info_crate_items); + for crate.node.module.items.each |&item| { + ebml_w.start_tag(tag_mod_child); + ebml_w.wr_str(def_to_str(local_def(item.id))); + ebml_w.end_tag(); + + for each_auxiliary_node_id(item) |auxiliary_node_id| { + ebml_w.start_tag(tag_mod_child); + ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id))); + ebml_w.end_tag(); + } + } + + // Encode reexports for the root module. + encode_reexports(ecx, ebml_w, 0, []); + + ebml_w.end_tag(); + ebml_w.end_tag(); +} + fn encode_crate_dep(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, dep: decoder::crate_dep) { @@ -1455,15 +1564,25 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { dep_bytes: 0, lang_item_bytes: 0, link_args_bytes: 0, + misc_bytes: 0, item_bytes: 0, index_bytes: 0, zero_bytes: 0, total_bytes: 0, n_inlines: 0 }; - let EncodeParams{item_symbols, diag, tcx, reexports2, - discrim_symbols, cstore, encode_inlined_item, - link_meta, _} = parms; + let EncodeParams { + item_symbols, + diag, + tcx, + reexports2, + discrim_symbols, + cstore, + encode_inlined_item, + link_meta, + reachable, + _ + } = parms; let type_abbrevs = @mut HashMap::new(); let stats = @mut stats; let ecx = EncodeContext { @@ -1476,7 +1595,8 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { link_meta: link_meta, cstore: cstore, encode_inlined_item: encode_inlined_item, - type_abbrevs: type_abbrevs + type_abbrevs: type_abbrevs, + reachable: reachable, }; let mut ebml_w = writer::Encoder(wr as @io::Writer); @@ -1502,6 +1622,11 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { encode_link_args(&ecx, &mut ebml_w); ecx.stats.link_args_bytes = *wr.pos - i; + // Encode miscellaneous info. + i = *wr.pos; + encode_misc_info(&ecx, crate, &mut ebml_w); + ecx.stats.misc_bytes = *wr.pos - i; + // Encode and index the items. ebml_w.start_tag(tag_items); i = *wr.pos; @@ -1529,6 +1654,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { io::println(fmt!(" dep bytes: %u", ecx.stats.dep_bytes)); io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes)); io::println(fmt!(" link args bytes: %u", ecx.stats.link_args_bytes)); + io::println(fmt!(" misc bytes: %u", ecx.stats.misc_bytes)); io::println(fmt!(" item bytes: %u", ecx.stats.item_bytes)); io::println(fmt!(" index bytes: %u", ecx.stats.index_bytes)); io::println(fmt!(" zero bytes: %u", ecx.stats.zero_bytes)); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 106c1d85cd77f..12ddd37104588 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -77,6 +77,15 @@ fn trait_method_might_be_inlined(trait_method: &trait_method) -> bool { } } +// The context we're in. If we're in a public context, then public symbols are +// marked reachable. If we're in a private context, then only trait +// implementations are marked reachable. +#[deriving(Eq)] +enum PrivacyContext { + PublicContext, + PrivateContext, +} + // Information needed while computing reachability. struct ReachableContext { // The type context. @@ -109,25 +118,31 @@ 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, (privacy_context, visitor): + (PrivacyContext, visit::vt)| { match item.node { item_fn(*) => { - reachable_symbols.insert(item.id); + if privacy_context == PublicContext { + 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) => { + Some(ctor_id) if + privacy_context == PublicContext => { reachable_symbols.insert(ctor_id); } + Some(_) | None => {} } } item_enum(ref enum_def, _) => { - for enum_def.variants.each |variant| { - reachable_symbols.insert(variant.node.id); + if privacy_context == PublicContext { + for enum_def.variants.each |variant| { + reachable_symbols.insert(variant.node.id); + } } } item_impl(ref generics, trait_ref, _, ref methods) => { @@ -137,9 +152,15 @@ impl ReachableContext { // treating implementations of reachable or cross- // crate traits as reachable. + let should_be_considered_public = |method: @method| { + (method.vis == public && + privacy_context == PublicContext) || + trait_ref.is_some() + }; + // Mark all public methods as reachable. - for methods.each |method| { - if method.vis == public || trait_ref.is_some() { + for methods.each |&method| { + if should_be_considered_public(method) { reachable_symbols.insert(method.id); } } @@ -147,9 +168,8 @@ impl ReachableContext { 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() { + for methods.each |&method| { + if should_be_considered_public(method) { worklist.push(method.id) } } @@ -161,8 +181,7 @@ impl ReachableContext { let attrs = &method.attrs; if generics_require_inlining(generics) || attributes_specify_inlining(*attrs) || - method.vis == public || - trait_ref.is_some() { + should_be_considered_public(*method) { worklist.push(method.id) } } @@ -170,27 +189,31 @@ impl ReachableContext { } 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) + if privacy_context == PublicContext { + for trait_methods.each |trait_method| { + match *trait_method { + provided(method) => { + reachable_symbols.insert(method.id); + worklist.push(method.id) + } + required(_) => {} } - required(_) => {} } } } _ => {} } - if item.vis == public { - visit::visit_item(item, ((), visitor)) + if item.vis == public && privacy_context == PublicContext { + visit::visit_item(item, (PublicContext, visitor)) + } else { + visit::visit_item(item, (PrivateContext, visitor)) } }, .. *visit::default_visitor() }); - visit::visit_crate(crate, ((), visitor)) + visit::visit_crate(crate, (PublicContext, visitor)) } // Returns true if the given def ID represents a local item that is @@ -247,7 +270,7 @@ impl ReachableContext { } } Some(_) => false, - None => tcx.sess.bug("def ID not in def map?!"), + None => false // This will happen for default methods. } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 778d6e1f68550..7e0c2dab83d16 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -654,7 +654,17 @@ impl NameBindings { Some(ref type_def) => { match (*type_def).type_def { Some(type_def) => Some(type_def), - None => None, + None => { + match type_def.module_def { + Some(module) => { + match module.def_id { + Some(did) => Some(def_mod(did)), + None => None, + } + } + None => None, + } + } } } } @@ -3149,12 +3159,14 @@ impl Resolver { Some(def_id) if def_id.crate == local_crate => { // OK. Continue. debug!("(recording exports for module subtree) recording \ - exports for local module"); + exports for local module `%s`", + self.module_to_str(module_)); } None => { // Record exports for the root module. debug!("(recording exports for module subtree) recording \ - exports for root module"); + exports for root module `%s`", + self.module_to_str(module_)); } Some(_) => { // Bail out. @@ -5037,6 +5049,9 @@ impl Resolver { self.trait_map.insert(expr.id, @mut traits); } expr_method_call(_, _, ident, _, _, _) => { + debug!("(recording candidate traits for expr) recording \ + traits for %d", + expr.id); let traits = self.search_for_traits_containing_method(ident); self.trait_map.insert(expr.id, @mut traits); } @@ -5112,7 +5127,6 @@ impl Resolver { debug!("(searching for traits containing method) looking for '%s'", self.session.str_of(name)); - let mut found_traits = ~[]; let mut search_module = self.current_module; match self.method_map.find(&name) { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 479f0cd71186a..6cb1c51176f95 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -64,7 +64,7 @@ use util::ppaux::{Repr, ty_to_str}; use middle::trans::type_::Type; use core::hash; -use core::hashmap::{HashMap}; +use core::hashmap::{HashMap, HashSet}; use core::int; use core::io; use core::libc::c_uint; @@ -2519,7 +2519,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef { variant)) } }; - if !exprt { + if !exprt && !ccx.reachable.contains(&id) { lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); } ccx.item_vals.insert(id, val); @@ -2823,13 +2823,13 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::encode_ encoder::EncodeParams { diag: diag, tcx: cx.tcx, - reachable: cx.reachable, reexports2: cx.exp_map2, item_symbols: item_symbols, discrim_symbols: discrim_symbols, link_meta: link_meta, cstore: cx.sess.cstore, - encode_inlined_item: ie + encode_inlined_item: ie, + reachable: cx.reachable, } } @@ -2897,7 +2897,7 @@ pub fn trans_crate(sess: session::Session, emap2: resolve::ExportMap2, reachable_map: @mut HashSet, maps: astencode::Maps) - -> (ModuleRef, LinkMeta) { + -> (ContextRef, ModuleRef, LinkMeta) { let mut symbol_hasher = hash::default_state(); let link_meta = link::build_link_meta(sess, crate, output, &mut symbol_hasher); @@ -2918,8 +2918,15 @@ pub fn trans_crate(sess: session::Session, // sess.bug("couldn't enable multi-threaded LLVM"); // } - let ccx = @mut CrateContext::new(sess, llmod_id, tcx, emap2, maps, - symbol_hasher, link_meta, reachable); + let ccx = @mut CrateContext::new(sess, + llmod_id, + tcx, + emap2, + maps, + symbol_hasher, + link_meta, + reachable_map); + { let _icx = push_ctxt("data"); trans_constants(ccx, crate); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 3e583e3aa25f4..f7a02a78d9917 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -123,84 +123,7 @@ pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res { } } -pub type ExternMap = @mut HashMap<@str, ValueRef>; - -// Crate context. Every crate we compile has one of these. -pub struct CrateContext { - sess: session::Session, - llmod: ModuleRef, - td: TargetData, - tn: @TypeNames, - externs: ExternMap, - intrinsics: HashMap<&'static str, ValueRef>, - item_vals: @mut HashMap, - exp_map2: resolve::ExportMap2, - item_symbols: @mut HashMap, - link_meta: LinkMeta, - enum_sizes: @mut HashMap, - discrims: @mut HashMap, - discrim_symbols: @mut HashMap, - tydescs: @mut HashMap, - // Set when running emit_tydescs to enforce that no more tydescs are - // created. - finished_tydescs: @mut bool, - // Track mapping of external ids to local items imported for inlining - external: @mut HashMap>, - // Cache instances of monomorphized functions - monomorphized: @mut HashMap, - monomorphizing: @mut HashMap, - // Cache computed type parameter uses (see type_use.rs) - type_use_cache: @mut HashMap, - // Cache generated vtables - vtables: @mut HashMap, - // Cache of constant strings, - const_cstr_cache: @mut HashMap<@str, ValueRef>, - - // Reverse-direction for const ptrs cast from globals. - // Key is an int, cast from a ValueRef holding a *T, - // Val is a ValueRef holding a *[T]. - // - // Needed because LLVM loses pointer->pointee association - // when we ptrcast, and we have to ptrcast during translation - // of a [T] const because we form a slice, a [*T,int] pair, not - // a pointer to an LLVM array type. - const_globals: @mut HashMap, - - // Cache of emitted const values - const_values: @mut HashMap, - - // Cache of external const values - extern_const_values: @mut HashMap, - - module_data: @mut HashMap<~str, ValueRef>, - lltypes: @mut HashMap, - llsizingtypes: @mut HashMap, - adt_reprs: @mut HashMap, - names: namegen, - next_addrspace: addrspace_gen, - symbol_hasher: @mut hash::State, - type_hashcodes: @mut HashMap, - type_short_names: @mut HashMap, - all_llvm_symbols: @mut HashSet<@str>, - tcx: ty::ctxt, - maps: astencode::Maps, - stats: @mut Stats, - upcalls: @upcall::Upcalls, - tydesc_type: TypeRef, - int_type: TypeRef, - float_type: TypeRef, - opaque_vec_type: TypeRef, - builder: BuilderRef_res, - shape_cx: shape::Ctxt, - crate_map: ValueRef, - // Set when at least one function uses GC. Needed so that - // decl_gc_metadata knows whether to link to the module metadata, which - // 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, - reachable_map: @mut HashSet, -} +pub type ExternMap = HashMap<@str, ValueRef>; // Types used for llself. pub struct ValSelfData { diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index a0ae579c86554..9e178b978cc7c 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -21,7 +21,6 @@ use middle::resolve; use middle::trans::adt; use middle::trans::base; use middle::trans::debuginfo; -use middle::trans::reachable; use middle::trans::type_use; use middle::ty; @@ -49,7 +48,7 @@ pub struct CrateContext { intrinsics: HashMap<&'static str, ValueRef>, item_vals: HashMap, exp_map2: resolve::ExportMap2, - reachable: reachable::map, + reachable: @mut HashSet, item_symbols: HashMap, link_meta: LinkMeta, enum_sizes: HashMap, @@ -117,10 +116,15 @@ pub struct CrateContext { } impl CrateContext { - pub fn new(sess: session::Session, name: &str, tcx: ty::ctxt, - emap2: resolve::ExportMap2, maps: astencode::Maps, - symbol_hasher: hash::State, link_meta: LinkMeta, - reachable: reachable::map) -> CrateContext { + pub fn new(sess: session::Session, + name: &str, + tcx: ty::ctxt, + emap2: resolve::ExportMap2, + maps: astencode::Maps, + symbol_hasher: hash::State, + link_meta: LinkMeta, + reachable: @mut HashSet) + -> CrateContext { unsafe { let llcx = llvm::LLVMContextCreate(); set_task_llcx(llcx); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d224d182950d3..4c1c8e5c2c8a3 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1393,6 +1393,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, method_map.insert(expr.id, (*entry)); } None => { + debug!("(checking method call) failing expr is %d", expr.id); + fcx.type_error_message(expr.span, |actual| { fmt!("type `%s` does not implement any method in scope \ diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 6da9895534b03..13a551d66c03b 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -17,7 +17,7 @@ use core::prelude::*; use metadata::csearch::{each_path, get_impl_trait}; -use metadata::csearch::{get_impls_for_mod}; +use metadata::csearch; use metadata::cstore::{CStore, iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use middle::resolve::{Impl, MethodInfo}; @@ -855,92 +855,67 @@ impl CoherenceChecker { // External crate handling - pub fn add_impls_for_module(&self, - impls_seen: &mut HashSet, - crate_store: @mut CStore, - module_def_id: def_id) { - let implementations = get_impls_for_mod(crate_store, - module_def_id, - None); - for implementations.iter().advance |implementation| { - debug!("coherence: adding impl from external crate: %s", - ty::item_path_str(self.crate_context.tcx, - implementation.did)); - - // Make sure we don't visit the same implementation - // multiple times. - if !impls_seen.insert(implementation.did) { - // Skip this one. - loop; - } - // Good. Continue. - - let self_type = lookup_item_type(self.crate_context.tcx, - implementation.did); - let associated_traits = get_impl_trait(self.crate_context.tcx, - implementation.did); - - // Do a sanity check to make sure that inherent methods have base - // types. - - if associated_traits.is_none() { - match get_base_type_def_id(self.inference_context, - dummy_sp(), - self_type.ty) { - None => { - let session = self.crate_context.tcx.sess; - session.bug(fmt!( - "no base type for external impl \ - with no trait: %s (type %s)!", - session.str_of(implementation.ident), - ty_to_str(self.crate_context.tcx,self_type.ty))); - } - Some(_) => { - // Nothing to do. - } - } - } - - let mut implementation = *implementation; + pub fn add_external_impl(&self, + impls_seen: &mut HashSet, + crate_store: @mut CStore, + impl_def_id: def_id) { + let implementation = csearch::get_impl(crate_store, impl_def_id); - // Record all the trait methods. - for associated_traits.iter().advance |trait_ref| { - self.instantiate_default_methods(implementation.did, - &**trait_ref); - // Could we avoid these copies when we don't need them? - let mut methods = /*bad?*/ copy implementation.methods; - self.add_provided_methods_to_impl( - &mut methods, - &trait_ref.def_id, - &implementation.did); - implementation = @Impl { methods: methods, - .. *implementation }; + debug!("coherence: adding impl from external crate: %s", + ty::item_path_str(self.crate_context.tcx, implementation.did)); + // Make sure we don't visit the same implementation multiple times. + if !impls_seen.insert(implementation.did) { + // Skip this one. + return + } + // Good. Continue. - self.add_trait_method(trait_ref.def_id, implementation); - } - - // Add the implementation to the mapping from - // implementation to base type def ID, if there is a base - // type for this implementation. + let self_type = lookup_item_type(self.crate_context.tcx, + implementation.did); + let associated_traits = get_impl_trait(self.crate_context.tcx, + implementation.did); + // Do a sanity check to make sure that inherent methods have base + // types. + if associated_traits.is_none() { match get_base_type_def_id(self.inference_context, - dummy_sp(), - self_type.ty) { + dummy_sp(), + self_type.ty) { None => { - // Nothing to do. + let session = self.crate_context.tcx.sess; + session.bug(fmt!("no base type for external impl with no \ + trait: %s (type %s)!", + session.str_of(implementation.ident), + ty_to_str(self.crate_context.tcx, + self_type.ty))); } - Some(base_type_def_id) => { - // inherent methods apply to `impl Type` but not - // `impl Trait for Type`: - if associated_traits.is_none() { - self.add_inherent_method(base_type_def_id, - implementation); - } + Some(_) => {} // Nothing to do. + } + } + + // Record all the trait methods. + let implementation = @implementation; + for associated_traits.iter().advance |trait_ref| { + self.add_trait_method(trait_ref.def_id, implementation); + } - self.base_type_def_ids.insert(implementation.did, - base_type_def_id); + // Add the implementation to the mapping from implementation to base + // type def ID, if there is a base type for this implementation. + match get_base_type_def_id(self.inference_context, + dummy_sp(), + self_type.ty) { + None => {} // Nothing to do. + Some(base_type_def_id) => { + // inherent methods apply to `impl Type` but not + // `impl Trait for Type`: + if associated_traits.is_none() { + self.add_inherent_method(base_type_def_id, + implementation); } + + self.base_type_def_ids.insert(implementation.did, + base_type_def_id); } } } @@ -952,22 +927,17 @@ impl CoherenceChecker { let crate_store = self.crate_context.tcx.sess.cstore; do iter_crate_data(crate_store) |crate_number, _crate_metadata| { - self.add_impls_for_module(&mut impls_seen, - crate_store, - def_id { crate: crate_number, - node: 0 }); - for each_path(crate_store, crate_number) |_, def_like, _| { match def_like { - dl_def(def_mod(def_id)) => { - self.add_impls_for_module(&mut impls_seen, - crate_store, - def_id); + dl_def(def_trait(def_id)) => { + self.add_default_methods_for_external_trait(def_id); } - dl_def(_) | dl_impl(_) | dl_field => { - // Skip this. - loop; + dl_impl(def_id) => { + self.add_external_impl(&mut impls_seen, + crate_store, + def_id) } + dl_def(_) | dl_field => loop, // Skip this. } } } diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 797fd9e8c020e..8f0870af51332 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -10,6 +10,7 @@ //! Utilities for manipulating the char type +use container::Container; use option::{None, Option, Some}; use str; use str::{StrSlice, OwnedStr}; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 0f6517f579981..f76489007d9cb 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -29,6 +29,7 @@ #[allow(missing_doc)]; use cast; +use container::Container; use io; use iterator::IteratorUtil; use libc; @@ -1501,7 +1502,10 @@ mod tests { fn test_getenv_big() { let mut s = ~""; let mut i = 0; - while i < 100 { s += "aaaaaaaaaa"; i += 1; } + while i < 100 { + s = s + "aaaaaaaaaa"; + i += 1; + } let n = make_rand_name(); setenv(n, s); debug!(copy s); diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 8a6c05ce6e2ae..5baff8aee68dd 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -42,6 +42,7 @@ fn main () { use cast; use cmp; +use container::Container; use int; use iterator::IteratorUtil; use local_data; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index ae2af203ca6d4..6a78e7822e33d 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1140,6 +1140,17 @@ impl<'self> Str for @str { } } +impl<'self> Container for &'self str { + #[inline] + fn len(&self) -> uint { + do as_buf(*self) |_p, n| { n - 1u } + } + #[inline] + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + #[allow(missing_doc)] pub trait StrSlice<'self> { fn contains<'a>(&self, needle: &'a str) -> bool; @@ -1158,10 +1169,8 @@ pub trait StrSlice<'self> { fn any_line_iter(&self) -> AnyLineIterator<'self>; fn word_iter(&self) -> WordIterator<'self>; fn ends_with(&self, needle: &str) -> bool; - fn is_empty(&self) -> bool; fn is_whitespace(&self) -> bool; fn is_alphanumeric(&self) -> bool; - fn len(&self) -> uint; fn char_len(&self) -> uint; fn slice(&self, begin: uint, end: uint) -> &'self str; @@ -1362,9 +1371,6 @@ impl<'self> StrSlice<'self> for &'self str { self.split_iter(char::is_whitespace).filter(|s| !s.is_empty()) } - /// Returns true if the string has length 0 - #[inline] - fn is_empty(&self) -> bool { self.len() == 0 } /** * Returns true if the string contains only whitespace * @@ -1379,11 +1385,6 @@ impl<'self> StrSlice<'self> for &'self str { */ #[inline] fn is_alphanumeric(&self) -> bool { self.iter().all(char::is_alphanumeric) } - /// Returns the size in bytes not counting the null terminator - #[inline] - fn len(&self) -> uint { - do as_buf(*self) |_p, n| { n - 1u } - } /// Returns the number of characters that a string holds #[inline] fn char_len(&self) -> uint { self.iter().len_() } diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs index 87bd25bdad322..624062a7ec407 100644 --- a/src/libstd/unstable/extfmt.rs +++ b/src/libstd/unstable/extfmt.rs @@ -94,6 +94,7 @@ use iterator::IteratorUtil; #[doc(hidden)] pub mod ct { use char; + use container::Container; use prelude::*; use str; From a9625502ad8580ef988d9a7d716e6c1f831d8aaf Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 25 Jun 2013 18:25:27 -0700 Subject: [PATCH 14/18] librustc: Fix merge fallout and test cases. --- src/libextra/crypto/digest.rs | 4 +- src/libextra/terminfo/parm.rs | 3 +- src/librustc/driver/session.rs | 8 +- src/librustc/metadata/encoder.rs | 8 +- src/librustc/middle/reachable.rs | 10 +- src/librustc/middle/resolve.rs | 2 +- src/librustc/middle/trans/build.rs | 2 +- src/librustc/middle/trans/cabi_x86_64.rs | 6 +- src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/check/method.rs | 11 +- src/librustc/middle/typeck/coherence.rs | 19 +- src/librustc/util/ppaux.rs | 4 +- src/librusti/rusti.rc | 666 ++++++++++++++++++ src/librustpkg/tests.rs | 2 +- src/libstd/to_str.rs | 2 +- src/libsyntax/parse/token.rs | 2 +- .../compile-fail/closure-bounds-subtype.rs | 4 +- .../compile-fail/impl-duplicate-methods.rs | 2 +- .../compile-fail/trait-bounds-cant-coerce.rs | 8 +- .../trait-bounds-not-on-bare-trait.rs | 2 +- .../trait-bounds-not-on-struct.rs | 2 +- .../compile-fail/trait-duplicate-methods.rs | 2 +- .../compile-fail/trait-or-new-type-instead.rs | 2 +- .../closure-bounds-can-capture-chan.rs | 2 +- src/test/run-pass/trait-bounds-basic.rs | 6 +- src/test/run-pass/trait-default-method-xc.rs | 8 +- 26 files changed, 743 insertions(+), 46 deletions(-) create mode 100644 src/librusti/rusti.rc diff --git a/src/libextra/crypto/digest.rs b/src/libextra/crypto/digest.rs index 8fd44bfc9abc4..c4fb03a7a7dea 100644 --- a/src/libextra/crypto/digest.rs +++ b/src/libextra/crypto/digest.rs @@ -49,9 +49,9 @@ fn to_hex(rr: &[u8]) -> ~str { for rr.iter().advance() |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/terminfo/parm.rs b/src/libextra/terminfo/parm.rs index dca890ddf5160..5180a71939c3a 100644 --- a/src/libextra/terminfo/parm.rs +++ b/src/libextra/terminfo/parm.rs @@ -470,13 +470,14 @@ priv fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> { FormatHex|FormatHEX => 16, FormatString => util::unreachable() }; - let mut (s,_) = match op { + let (s,_) = match op { FormatDigit => { let sign = if flags.sign { SignAll } else { SignNeg }; to_str_bytes_common(&d, radix, false, sign, DigAll) } _ => to_str_bytes_common(&(d as uint), radix, false, SignNone, DigAll) }; + let mut s = s; if flags.precision > s.len() { let mut s_ = vec::with_capacity(flags.precision); let n = flags.precision - s.len(); diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index b5eb351a8a589..ec86b43ffa3c6 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -403,8 +403,12 @@ mod test { fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate { let mut attrs = ~[]; - if with_bin { attrs += [make_crate_type_attr(@"bin")]; } - if with_lib { attrs += [make_crate_type_attr(@"lib")]; } + if with_bin { + attrs.push(make_crate_type_attr(@"bin")); + } + if with_lib { + attrs.push(make_crate_type_attr(@"lib")); + } @codemap::respan(codemap::dummy_sp(), ast::crate_ { module: ast::_mod { view_items: ~[], items: ~[] }, attrs: attrs, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 187f2a99ed4c5..e394c8dcf92f9 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -484,7 +484,7 @@ fn each_auxiliary_node_id(item: @item, callback: &fn(node_id) -> bool) let mut continue = true; match item.node { item_enum(ref enum_def, _) => { - for enum_def.variants.each |variant| { + for enum_def.variants.iter().advance |variant| { continue = callback(variant.node.id); if !continue { break @@ -516,7 +516,7 @@ fn encode_reexports(ecx: &EncodeContext, match ecx.reexports2.find(&id) { Some(ref exports) => { debug!("(encoding info for module) found reexports for %d", id); - for exports.each |exp| { + for exports.iter().advance |exp| { debug!("(encoding info for module) reexport '%s' for %d", exp.name, id); ebml_w.start_tag(tag_items_data_item_reexport); @@ -900,7 +900,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); // Encode all the items in this module. - for fm.items.each |foreign_item| { + for fm.items.iter().advance |foreign_item| { ebml_w.start_tag(tag_mod_child); ebml_w.wr_str(def_to_str(local_def(foreign_item.id))); ebml_w.end_tag(); @@ -1506,7 +1506,7 @@ fn encode_misc_info(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { ebml_w.start_tag(tag_misc_info); ebml_w.start_tag(tag_misc_info_crate_items); - for crate.node.module.items.each |&item| { + for crate.node.module.items.iter().advance |&item| { ebml_w.start_tag(tag_mod_child); ebml_w.wr_str(def_to_str(local_def(item.id))); ebml_w.end_tag(); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 12ddd37104588..fe7eccf9d594a 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -140,7 +140,7 @@ impl ReachableContext { } item_enum(ref enum_def, _) => { if privacy_context == PublicContext { - for enum_def.variants.each |variant| { + for enum_def.variants.iter().advance |variant| { reachable_symbols.insert(variant.node.id); } } @@ -159,7 +159,7 @@ impl ReachableContext { }; // Mark all public methods as reachable. - for methods.each |&method| { + for methods.iter().advance |&method| { if should_be_considered_public(method) { reachable_symbols.insert(method.id); } @@ -168,7 +168,7 @@ impl ReachableContext { if generics_require_inlining(generics) { // If the impl itself has generics, add all public // symbols to the worklist. - for methods.each |&method| { + for methods.iter().advance |&method| { if should_be_considered_public(method) { worklist.push(method.id) } @@ -176,7 +176,7 @@ impl ReachableContext { } else { // Otherwise, add only public methods that have // generics to the worklist. - for methods.each |method| { + for methods.iter().advance |method| { let generics = &method.generics; let attrs = &method.attrs; if generics_require_inlining(generics) || @@ -190,7 +190,7 @@ impl ReachableContext { item_trait(_, _, ref trait_methods) => { // Mark all provided methods as reachable. if privacy_context == PublicContext { - for trait_methods.each |trait_method| { + for trait_methods.iter().advance |trait_method| { match *trait_method { provided(method) => { reachable_symbols.insert(method.id); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 7e0c2dab83d16..a1b6132195bdd 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1240,7 +1240,7 @@ impl Resolver { // Create the module and add all methods. match *ty { Ty { - node: ty_path(path, _), + node: ty_path(path, _, _), _ } if path.idents.len() == 1 => { let name = path_to_ident(path); diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index e48a98cd90c0f..dc32a3b4e2c88 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -616,7 +616,7 @@ pub fn GEPi(cx: block, base: ValueRef, ixs: &[uint]) -> ValueRef { // we care about. if ixs.len() < 16 { let mut small_vec = [ C_i32(0), ..16 ]; - for ixs.eachi |i, &ix| { + for ixs.iter().enumerate().advance |(i, &ix)| { small_vec[i] = C_i32(ix as i32) } InBoundsGEP(cx, base, small_vec.slice(0, ixs.len())) diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index 23542ca905b9f..5cc40f71a2aab 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -39,7 +39,11 @@ enum RegClass { Memory } -impl Type { +trait TypeMethods { + fn is_reg_ty(&self) -> bool; +} + +impl TypeMethods for Type { fn is_reg_ty(&self) -> bool { match self.kind() { Integer | Pointer | Float | Double => true, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fb50848dc0ad8..a81a4e020c3e2 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1908,7 +1908,7 @@ impl TypeContents { // this assertion. assert!(self.intersects(TC_OWNED_POINTER)); } - let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx); + let tc = TC_MANAGED + TC_DTOR + TypeContents::sendable(cx); self.intersects(tc) } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 777b11186c6ff..705e6e52d34a4 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1086,16 +1086,19 @@ impl<'self> LookupContext<'self> { _ => {} } - return match candidate.method_ty.explicit_self { + let result = match candidate.method_ty.explicit_self { sty_static => { + debug!("(is relevant?) explicit self is static"); false } sty_value => { + debug!("(is relevant?) explicit self is by-value"); self.fcx.can_mk_subty(rcvr_ty, candidate.rcvr_ty).is_ok() } sty_region(_, m) => { + debug!("(is relevant?) explicit self is a region"); match ty::get(rcvr_ty).sty { ty::ty_rptr(_, mt) => { mutability_matches(mt.mutbl, m) && @@ -1107,6 +1110,7 @@ impl<'self> LookupContext<'self> { } sty_box(m) => { + debug!("(is relevant?) explicit self is a box"); match ty::get(rcvr_ty).sty { ty::ty_box(mt) => { mutability_matches(mt.mutbl, m) && @@ -1118,6 +1122,7 @@ impl<'self> LookupContext<'self> { } sty_uniq(m) => { + debug!("(is relevant?) explicit self is a unique pointer"); match ty::get(rcvr_ty).sty { ty::ty_uniq(mt) => { mutability_matches(mt.mutbl, m) && @@ -1129,6 +1134,10 @@ impl<'self> LookupContext<'self> { } }; + debug!("(is relevant?) %s", if result { "yes" } else { "no" }); + + return result; + fn mutability_matches(self_mutbl: ast::mutability, candidate_mutbl: ast::mutability) -> bool { //! True if `self_mutbl <: candidate_mutbl` diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 13a551d66c03b..cb297f31686f6 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -895,8 +895,22 @@ impl CoherenceChecker { } // Record all the trait methods. - let implementation = @implementation; + let mut implementation = @implementation; for associated_traits.iter().advance |trait_ref| { + self.instantiate_default_methods(implementation.did, + *trait_ref); + + // XXX(sully): We could probably avoid this copy if there are no + // default methods. + let mut methods = copy implementation.methods; + self.add_provided_methods_to_impl(&mut methods, + &trait_ref.def_id, + &implementation.did); + implementation = @Impl { + methods: methods, + ..*implementation + }; + self.add_trait_method(trait_ref.def_id, implementation); } @@ -929,9 +943,6 @@ impl CoherenceChecker { do iter_crate_data(crate_store) |crate_number, _crate_metadata| { for each_path(crate_store, crate_number) |_, def_like, _| { match def_like { - dl_def(def_trait(def_id)) => { - self.add_default_methods_for_external_trait(def_id); - } dl_impl(def_id) => { self.add_external_impl(&mut impls_seen, crate_store, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 58dc121959ed2..548eebaea0bea 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -488,7 +488,9 @@ pub fn parameterized(cx: ctxt, } }; - strs += vec::map(tps, |t| ty_to_str(cx, *t)); + for tps.iter().advance |t| { + strs.push(ty_to_str(cx, *t)) + } if strs.len() > 0u { fmt!("%s<%s>", base, strs.connect(",")) diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc new file mode 100644 index 0000000000000..5873f361ad734 --- /dev/null +++ b/src/librusti/rusti.rc @@ -0,0 +1,666 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * rusti - A REPL using the JIT backend + * + * Rusti works by serializing state between lines of input. This means that each + * line can be run in a separate task, and the only limiting factor is that all + * local bound variables are encodable. + * + * This is accomplished by feeding in generated input to rustc for execution in + * the JIT compiler. Currently input actually gets fed in three times to get + * information about the program. + * + * - Pass #1 + * In this pass, the input is simply thrown at the parser and the input comes + * back. This validates the structure of the program, and at this stage the + * global items (fns, structs, impls, traits, etc.) are filtered from the + * input into the "global namespace". These declarations shadow all previous + * declarations of an item by the same name. + * + * - Pass #2 + * After items have been stripped, the remaining input is passed to rustc + * along with all local variables declared (initialized to nothing). This pass + * runs up to typechecking. From this, we can learn about the types of each + * bound variable, what variables are bound, and also ensure that all the + * types are encodable (the input can actually be run). + * + * - Pass #3 + * Finally, a program is generated to deserialize the local variable state, + * run the code input, and then reserialize all bindings back into a local + * hash map. Once this code runs, the input has fully been run and the REPL + * waits for new input. + * + * Encoding/decoding is done with EBML, and there is simply a map of ~str -> + * ~[u8] maintaining the values of each local binding (by name). + */ + +#[link(name = "rusti", + vers = "0.7-pre", + uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc", + url = "https://github.com/mozilla/rust/tree/master/src/rusti")]; + +#[license = "MIT/ASL2"]; +#[crate_type = "lib"]; + +extern mod extra; +extern mod rustc; +extern mod syntax; + +use std::{libc, io, os, task, vec}; +use std::cell::Cell; +use extra::rl; + +use rustc::driver::{driver, session}; +use syntax::{ast, diagnostic}; +use syntax::ast_util::*; +use syntax::parse::token; +use syntax::print::pprust; + +use program::Program; +use utils::*; + +mod program; +pub mod utils; + +/** + * A structure shared across REPL instances for storing history + * such as statements and view items. I wish the AST was sendable. + */ +pub struct Repl { + prompt: ~str, + binary: ~str, + running: bool, + lib_search_paths: ~[~str], + + program: Program, +} + +// Action to do after reading a :command +enum CmdAction { + action_none, + action_run_line(~str), +} + +/// Run an input string in a Repl, returning the new Repl. +fn run(mut repl: Repl, input: ~str) -> Repl { + // Build some necessary rustc boilerplate for compiling things + let binary = repl.binary.to_managed(); + let options = @session::options { + crate_type: session::unknown_crate, + binary: binary, + addl_lib_search_paths: @mut repl.lib_search_paths.map(|p| Path(*p)), + jit: true, + .. copy *session::basic_options() + }; + // Because we assume that everything is encodable (and assert so), add some + // extra helpful information if the error crops up. Otherwise people are + // bound to be very confused when they find out code is running that they + // never typed in... + let sess = driver::build_session(options, |cm, msg, lvl| { + diagnostic::emit(cm, msg, lvl); + if msg.contains("failed to find an implementation of trait") && + msg.contains("extra::serialize::Encodable") { + diagnostic::emit(cm, + "Currrently rusti serializes bound locals between \ + different lines of input. This means that all \ + values of local variables need to be encodable, \ + and this type isn't encodable", + diagnostic::note); + } + }); + let intr = token::get_ident_interner(); + + // + // Stage 1: parse the input and filter it into the program (as necessary) + // + debug!("parsing: %s", input); + let crate = parse_input(sess, binary, input); + let mut to_run = ~[]; // statements to run (emitted back into code) + let new_locals = @mut ~[]; // new locals being defined + let mut result = None; // resultant expression (to print via pp) + do find_main(crate, sess) |blk| { + // Fish out all the view items, be sure to record 'extern mod' items + // differently beause they must appear before all 'use' statements + for blk.node.view_items.iter().advance |vi| { + let s = do with_pp(intr) |pp, _| { + pprust::print_view_item(pp, *vi); + }; + match vi.node { + ast::view_item_extern_mod(*) => { + repl.program.record_extern(s); + } + ast::view_item_use(*) => { repl.program.record_view_item(s); } + } + } + + // Iterate through all of the block's statements, inserting them into + // the correct portions of the program + for blk.node.stmts.iter().advance |stmt| { + let s = do with_pp(intr) |pp, _| { pprust::print_stmt(pp, *stmt); }; + match stmt.node { + ast::stmt_decl(d, _) => { + match d.node { + ast::decl_item(it) => { + let name = sess.str_of(it.ident); + match it.node { + // Structs are treated specially because to make + // them at all usable they need to be decorated + // with #[deriving(Encoable, Decodable)] + ast::item_struct(*) => { + repl.program.record_struct(name, s); + } + // Item declarations are hoisted out of main() + _ => { repl.program.record_item(name, s); } + } + } + + // Local declarations must be specially dealt with, + // record all local declarations for use later on + ast::decl_local(l) => { + let mutbl = l.node.is_mutbl; + do each_binding(l) |path, _| { + let s = do with_pp(intr) |pp, _| { + pprust::print_path(pp, path, false); + }; + new_locals.push((s, mutbl)); + } + to_run.push(s); + } + } + } + + // run statements with expressions (they have effects) + ast::stmt_mac(*) | ast::stmt_semi(*) | ast::stmt_expr(*) => { + to_run.push(s); + } + } + } + result = do blk.node.expr.map_consume |e| { + do with_pp(intr) |pp, _| { pprust::print_expr(pp, e); } + }; + } + // return fast for empty inputs + if to_run.len() == 0 && result.is_none() { + return repl; + } + + // + // Stage 2: run everything up to typeck to learn the types of the new + // variables introduced into the program + // + info!("Learning about the new types in the program"); + repl.program.set_cache(); // before register_new_vars (which changes them) + let input = to_run.connect("\n"); + let test = repl.program.test_code(input, &result, *new_locals); + debug!("testing with ^^^^^^ %?", (||{ println(test) })()); + let dinput = driver::str_input(test.to_managed()); + let cfg = driver::build_configuration(sess, binary, &dinput); + let outputs = driver::build_output_filenames(&dinput, &None, &None, [], sess); + let (crate, tcx) = driver::compile_upto(sess, copy cfg, &dinput, + driver::cu_typeck, Some(outputs)); + // Once we're typechecked, record the types of all local variables defined + // in this input + do find_main(crate.expect("crate after cu_typeck"), sess) |blk| { + repl.program.register_new_vars(blk, tcx.expect("tcx after cu_typeck")); + } + + // + // Stage 3: Actually run the code in the JIT + // + info!("actually running code"); + let code = repl.program.code(input, &result); + debug!("actually running ^^^^^^ %?", (||{ println(code) })()); + let input = driver::str_input(code.to_managed()); + let cfg = driver::build_configuration(sess, binary, &input); + let outputs = driver::build_output_filenames(&input, &None, &None, [], sess); + let sess = driver::build_session(options, diagnostic::emit); + driver::compile_upto(sess, cfg, &input, driver::cu_everything, + Some(outputs)); + + // + // Stage 4: Inform the program that computation is done so it can update all + // local variable bindings. + // + info!("cleaning up after code"); + repl.program.consume_cache(); + + return repl; + + fn parse_input(sess: session::Session, binary: @str, + input: &str) -> @ast::crate { + let code = fmt!("fn main() {\n %s \n}", input); + let input = driver::str_input(code.to_managed()); + let cfg = driver::build_configuration(sess, binary, &input); + let outputs = driver::build_output_filenames(&input, &None, &None, [], sess); + let (crate, _) = driver::compile_upto(sess, cfg, &input, + driver::cu_parse, Some(outputs)); + crate.expect("parsing should return a crate") + } + + fn find_main(crate: @ast::crate, sess: session::Session, + f: &fn(&ast::blk)) { + for crate.node.module.items.iter().advance |item| { + match item.node { + ast::item_fn(_, _, _, _, ref blk) => { + if item.ident == sess.ident_of("main") { + return f(blk); + } + } + _ => {} + } + } + fail!("main function was expected somewhere..."); + } +} + +// Compiles a crate given by the filename as a library if the compiled +// version doesn't exist or is older than the source file. Binary is +// the name of the compiling executable. Returns Some(true) if it +// successfully compiled, Some(false) if the crate wasn't compiled +// because it already exists and is newer than the source file, or +// None if there were compile errors. +fn compile_crate(src_filename: ~str, binary: ~str) -> Option { + match do task::try { + let src_path = Path(src_filename); + let binary = binary.to_managed(); + let options = @session::options { + binary: binary, + addl_lib_search_paths: @mut ~[os::getcwd()], + .. copy *session::basic_options() + }; + let input = driver::file_input(copy src_path); + let sess = driver::build_session(options, diagnostic::emit); + *sess.building_library = true; + let cfg = driver::build_configuration(sess, binary, &input); + let outputs = driver::build_output_filenames( + &input, &None, &None, [], sess); + // If the library already exists and is newer than the source + // file, skip compilation and return None. + let mut should_compile = true; + let dir = os::list_dir_path(&Path(outputs.out_filename.dirname())); + let maybe_lib_path = do dir.iter().find_ |file| { + // The actual file's name has a hash value and version + // number in it which is unknown at this time, so looking + // for a file that matches out_filename won't work, + // instead we guess which file is the library by matching + // the prefix and suffix of out_filename to files in the + // directory. + let file_str = file.filename().get(); + file_str.starts_with(outputs.out_filename.filestem().get()) + && file_str.ends_with(outputs.out_filename.filetype().get()) + }; + match maybe_lib_path { + Some(lib_path) => { + let (src_mtime, _) = src_path.get_mtime().get(); + let (lib_mtime, _) = lib_path.get_mtime().get(); + if lib_mtime >= src_mtime { + should_compile = false; + } + }, + None => { }, + } + if (should_compile) { + println(fmt!("compiling %s...", src_filename)); + driver::compile_upto(sess, cfg, &input, driver::cu_everything, + Some(outputs)); + true + } else { false } + } { + Ok(true) => Some(true), + Ok(false) => Some(false), + Err(_) => None, + } +} + +/// Tries to get a line from rl after outputting a prompt. Returns +/// None if no input was read (e.g. EOF was reached). +fn get_line(use_rl: bool, prompt: &str) -> Option<~str> { + if use_rl { + let result = unsafe { rl::read(prompt) }; + + match result { + None => None, + Some(line) => { + unsafe { rl::add_history(line) }; + Some(line) + } + } + } else { + if io::stdin().eof() { + None + } else { + Some(io::stdin().read_line()) + } + } +} + +/// Run a command, e.g. :clear, :exit, etc. +fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, + cmd: ~str, args: ~[~str], use_rl: bool) -> CmdAction { + let mut action = action_none; + match cmd { + ~"exit" => repl.running = false, + ~"clear" => { + repl.program.clear(); + + // XXX: Win32 version of linenoise can't do this + //rl::clear(); + } + ~"help" => { + println( + ":{\\n ..lines.. \\n:}\\n - execute multiline command\n\ + :load ... - loads given crates as dynamic libraries\n\ + :clear - clear the bindings\n\ + :exit - exit from the repl\n\ + :help - show this message"); + } + ~"load" => { + let mut loaded_crates: ~[~str] = ~[]; + for args.iter().advance |arg| { + let (crate, filename) = + if arg.ends_with(".rs") || arg.ends_with(".rc") { + (arg.slice_to(arg.len() - 3).to_owned(), copy *arg) + } else { + (copy *arg, *arg + ".rs") + }; + match compile_crate(filename, copy repl.binary) { + Some(_) => loaded_crates.push(crate), + None => { } + } + } + for loaded_crates.iter().advance |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.iter().any_(|x| x == &crate_dir) { + repl.lib_search_paths.push(crate_dir); + } + } + if loaded_crates.is_empty() { + println("no crates loaded"); + } else { + println(fmt!("crates loaded: %s", + loaded_crates.connect(", "))); + } + } + ~"{" => { + let mut multiline_cmd = ~""; + let mut end_multiline = false; + while (!end_multiline) { + match get_line(use_rl, "rusti| ") { + None => fail!("unterminated multiline command :{ .. :}"), + Some(line) => { + if line.trim() == ":}" { + end_multiline = true; + } else { + multiline_cmd.push_str(line); + multiline_cmd.push_char('\n'); + } + } + } + } + action = action_run_line(multiline_cmd); + } + _ => println(~"unknown cmd: " + cmd) + } + return action; +} + +/// Executes a line of input, which may either be rust code or a +/// :command. Returns a new Repl if it has changed. +pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str, + use_rl: bool) + -> Option { + if line.starts_with(":") { + // drop the : and the \n (one byte each) + let full = line.slice(1, line.len()); + let split: ~[~str] = full.word_iter().transform(|s| s.to_owned()).collect(); + let len = split.len(); + + if len > 0 { + let cmd = copy split[0]; + + if !cmd.is_empty() { + let args = if len > 1 { + vec::slice(split, 1, len).to_owned() + } else { ~[] }; + + match run_cmd(repl, in, out, cmd, args, use_rl) { + action_none => { } + action_run_line(multiline_cmd) => { + if !multiline_cmd.is_empty() { + return run_line(repl, in, out, multiline_cmd, use_rl); + } + } + } + return None; + } + } + } + + let line = Cell::new(line); + let r = Cell::new(copy *repl); + let result = do task::try { + run(r.take(), line.take()) + }; + + if result.is_ok() { + return Some(result.get()); + } + return None; +} + +pub fn main() { + let args = os::args(); + let in = io::stdin(); + let out = io::stdout(); + let mut repl = Repl { + prompt: ~"rusti> ", + binary: copy args[0], + running: true, + lib_search_paths: ~[], + + program: Program::new(), + }; + + let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0; + + // only print this stuff if the user is actually typing into rusti + if istty { + println("WARNING: The Rust REPL is experimental and may be"); + println("unstable. If you encounter problems, please use the"); + println("compiler instead. Type :help for help."); + + unsafe { + do rl::complete |line, suggest| { + if line.starts_with(":") { + suggest(~":clear"); + suggest(~":exit"); + suggest(~":help"); + suggest(~":load"); + } + } + } + } + + while repl.running { + match get_line(istty, repl.prompt) { + None => break, + Some(line) => { + if line.is_empty() { + if istty { + println("()"); + } + loop; + } + match run_line(&mut repl, in, out, line, istty) { + Some(new_repl) => repl = new_repl, + None => { } + } + } + } + } +} + +#[cfg(test)] +mod tests { + use std::io; + use std::iterator::IteratorUtil; + use program::Program; + use super::*; + + fn repl() -> Repl { + Repl { + prompt: ~"rusti> ", + binary: ~"rusti", + running: true, + lib_search_paths: ~[], + program: Program::new(), + } + } + + fn run_program(prog: &str) { + let mut r = repl(); + for prog.split_iter('\n').advance |cmd| { + let result = run_line(&mut r, io::stdin(), io::stdout(), + cmd.to_owned(), false); + r = result.expect(fmt!("the command '%s' failed", cmd)); + } + } + + #[test] + // FIXME: #7220 rusti on 32bit mac doesn't work. + #[cfg(not(target_word_size="32", + target_os="macos"))] + fn run_all() { + // FIXME(#7071): + // By default, unit tests are run in parallel. Rusti, on the other hand, + // does not enjoy doing this. I suspect that it is because the LLVM + // bindings are not thread-safe (when running parallel tests, some tests + // were triggering assertions in LLVM (or segfaults). Hence, this + // function exists to run everything serially (sadface). + // + // To get some interesting output, run with RUST_LOG=rusti::tests + + debug!("hopefully this runs"); + run_program(""); + + debug!("regression test for #5937"); + run_program("use std::hashmap;"); + + debug!("regression test for #5784"); + run_program("let a = 3;"); + + // XXX: can't spawn new tasks because the JIT code is cleaned up + // after the main function is done. + // debug!("regression test for #5803"); + // run_program(" + // spawn( || println(\"Please don't segfault\") ); + // do spawn { println(\"Please?\"); } + // "); + + debug!("inferred integers are usable"); + run_program("let a = 2;\n()\n"); + run_program(" + let a = 3; + let b = 4u; + assert!((a as uint) + b == 7) + "); + + debug!("local variables can be shadowed"); + run_program(" + let a = 3; + let a = 5; + assert!(a == 5) + "); + + debug!("strings are usable"); + run_program(" + let a = ~\"\"; + let b = \"\"; + let c = @\"\"; + let d = a + b + c; + assert!(d.len() == 0); + "); + + debug!("vectors are usable"); + run_program(" + let a = ~[1, 2, 3]; + let b = &[1, 2, 3]; + let c = @[1, 2, 3]; + let d = a + b + c; + assert!(d.len() == 9); + let e: &[int] = []; + "); + + debug!("structs are usable"); + run_program(" + struct A{ a: int } + let b = A{ a: 3 }; + assert!(b.a == 3) + "); + + debug!("mutable variables"); + run_program(" + let mut a = 3; + a = 5; + let mut b = std::hashmap::HashSet::new::(); + b.insert(a); + assert!(b.contains(&5)) + assert!(b.len() == 1) + "); + + debug!("functions are cached"); + run_program(" + fn fib(x: int) -> int { if x < 2 {x} else { fib(x - 1) + fib(x - 2) } } + let a = fib(3); + let a = a + fib(4); + assert!(a == 5) + "); + + debug!("modules are cached"); + run_program(" + mod b { pub fn foo() -> uint { 3 } } + assert!(b::foo() == 3) + "); + + debug!("multiple function definitions are allowed"); + run_program(" + fn f() {} + fn f() {} + f() + "); + + debug!("multiple item definitions are allowed"); + run_program(" + fn f() {} + mod f {} + struct f; + enum f {} + fn f() {} + f() + "); + } + + #[test] + // FIXME: #7220 rusti on 32bit mac doesn't work. + #[cfg(not(target_word_size="32", + target_os="macos"))] + fn exit_quits() { + let mut r = repl(); + assert!(r.running); + let result = run_line(&mut r, io::stdin(), io::stdout(), + ~":exit", false); + assert!(result.is_none()); + assert!(!r.running); + } +} diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index afeb64075335b..ac492b29427a0 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -248,7 +248,7 @@ fn command_line_test_output(args: &[~str]) -> ~[~str] { let p_output = command_line_test(args, &os::getcwd()); let test_output = str::from_bytes(p_output.output); for test_output.split_iter('\n').advance |s| { - result += [s.to_owned()]; + result.push(s.to_owned()); } result } diff --git a/src/libstd/to_str.rs b/src/libstd/to_str.rs index dcd02744cf902..77701acd33e2e 100644 --- a/src/libstd/to_str.rs +++ b/src/libstd/to_str.rs @@ -55,7 +55,7 @@ impl ToStr for HashMap { fn to_str(&self) -> ~str { let mut acc = ~"{"; let mut first = true; - for self.iter().advance |key, value| { + for self.iter().advance |(key, value)| { if first { first = false; } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 18e6c1817991b..793626f0e1808 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -563,7 +563,7 @@ pub mod keywords { // Strict keywords As, Break, - Freeze, + Const, Copy, Do, Else, diff --git a/src/test/compile-fail/closure-bounds-subtype.rs b/src/test/compile-fail/closure-bounds-subtype.rs index 6ffdd0f541e14..0c9220d18ab76 100644 --- a/src/test/compile-fail/closure-bounds-subtype.rs +++ b/src/test/compile-fail/closure-bounds-subtype.rs @@ -8,7 +8,7 @@ fn take_copyable(_: &fn:Copy()) { fn take_copyable_owned(_: &fn:Copy+Send()) { } -fn take_const_owned(_: &fn:Const+Owned()) { +fn take_const_owned(_: &fn:Freeze+Send()) { } fn give_any(f: &fn:()) { @@ -33,7 +33,7 @@ fn give_copyable_owned(f: &fn:Copy+Send()) { take_any(f); take_copyable(f); take_copyable_owned(f); - take_const_owned(f); //~ ERROR expected bounds `Owned+Const` but found bounds `Copy+Owned` + take_const_owned(f); //~ ERROR expected bounds `Send+Freeze` but found bounds `Copy+Send` } fn main() {} diff --git a/src/test/compile-fail/impl-duplicate-methods.rs b/src/test/compile-fail/impl-duplicate-methods.rs index ec766e5ce9b93..c6ce4d04e1086 100644 --- a/src/test/compile-fail/impl-duplicate-methods.rs +++ b/src/test/compile-fail/impl-duplicate-methods.rs @@ -11,7 +11,7 @@ struct Foo; impl Foo { fn orange(&self){} - fn orange(&self){} //~ ERROR error: duplicate definition of method `orange` + fn orange(&self){} //~ ERROR error: duplicate definition of value `orange` } fn main() {} diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs index adaea1de9bd0f..a96da398f5a11 100644 --- a/src/test/compile-fail/trait-bounds-cant-coerce.rs +++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs @@ -11,14 +11,14 @@ trait Foo { } -fn a(_x: ~Foo:Owned) { +fn a(_x: ~Foo:Send) { } -fn b(_x: ~Foo:Owned+Copy) { +fn b(_x: ~Foo:Send+Copy) { } -fn c(x: ~Foo:Const+Owned) { - b(x); //~ ERROR expected bounds `Copy+Owned` +fn c(x: ~Foo:Freeze+Send) { + b(x); //~ ERROR expected bounds `Copy+Send` } fn d(x: ~Foo:) { diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs index e9cc9575003d9..d7c98ec4e9d24 100644 --- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs +++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs @@ -13,7 +13,7 @@ trait Foo { // This should emit the less confusing error, not the more confusing one. -fn foo(_x: Foo:Owned) { //~ERROR reference to trait `Foo` where a type is expected +fn foo(_x: Foo:Send) { //~ERROR reference to trait `Foo` where a type is expected } fn main() { } diff --git a/src/test/compile-fail/trait-bounds-not-on-struct.rs b/src/test/compile-fail/trait-bounds-not-on-struct.rs index 45bb5e29a884f..ebffd0303e047 100644 --- a/src/test/compile-fail/trait-bounds-not-on-struct.rs +++ b/src/test/compile-fail/trait-bounds-not-on-struct.rs @@ -10,6 +10,6 @@ struct Foo; -fn foo(_x: ~Foo:Owned) { } //~ ERROR kind bounds can only be used on trait types +fn foo(_x: ~Foo:Send) { } //~ ERROR kind bounds can only be used on trait types fn main() { } diff --git a/src/test/compile-fail/trait-duplicate-methods.rs b/src/test/compile-fail/trait-duplicate-methods.rs index e2ba5267eba8e..ba8101d16ab0f 100644 --- a/src/test/compile-fail/trait-duplicate-methods.rs +++ b/src/test/compile-fail/trait-duplicate-methods.rs @@ -10,7 +10,7 @@ trait Foo { fn orange(&self); - fn orange(&self); //~ ERROR error: duplicate definition of method `orange` + fn orange(&self); //~ ERROR error: duplicate definition of value `orange` } fn main() {} diff --git a/src/test/compile-fail/trait-or-new-type-instead.rs b/src/test/compile-fail/trait-or-new-type-instead.rs index f687a6f97024a..c44887593ab3c 100644 --- a/src/test/compile-fail/trait-or-new-type-instead.rs +++ b/src/test/compile-fail/trait-or-new-type-instead.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: implement a trait or new type instead +// error-pattern: found value name used as a type impl Option { pub fn foo(&self) { } } diff --git a/src/test/run-pass/closure-bounds-can-capture-chan.rs b/src/test/run-pass/closure-bounds-can-capture-chan.rs index 26bea0e514151..95b0c9d79b7cb 100644 --- a/src/test/run-pass/closure-bounds-can-capture-chan.rs +++ b/src/test/run-pass/closure-bounds-can-capture-chan.rs @@ -10,7 +10,7 @@ use std::comm; -fn foo(blk: ~fn:Owned()) { +fn foo(blk: ~fn:Send()) { blk(); } diff --git a/src/test/run-pass/trait-bounds-basic.rs b/src/test/run-pass/trait-bounds-basic.rs index 5bfbf84d8acac..e0d60d62bb582 100644 --- a/src/test/run-pass/trait-bounds-basic.rs +++ b/src/test/run-pass/trait-bounds-basic.rs @@ -14,14 +14,14 @@ trait Foo { fn a(_x: ~Foo:) { } -fn b(_x: ~Foo:Owned) { +fn b(_x: ~Foo:Send) { } -fn c(x: ~Foo:Const+Owned) { +fn c(x: ~Foo:Freeze+Send) { a(x); } -fn d(x: ~Foo:Owned+Copy) { +fn d(x: ~Foo:Send+Copy) { b(x); } diff --git a/src/test/run-pass/trait-default-method-xc.rs b/src/test/run-pass/trait-default-method-xc.rs index e6e5b8605a161..f6c119c4faeb3 100644 --- a/src/test/run-pass/trait-default-method-xc.rs +++ b/src/test/run-pass/trait-default-method-xc.rs @@ -44,12 +44,12 @@ fn main () { let a = thing { x: 0 }; let b = thing { x: 1 }; - assert_eq!(0i.g(), 10); + //assert_eq!(0i.g(), 10); assert_eq!(a.g(), 10); assert_eq!(a.h(), 10); - assert_eq!(0i.thing(3.14, 1), (3.14, 1)); + //assert_eq!(0i.thing(3.14, 1), (3.14, 1)); assert_eq!(g(0i, 3.14, 1), (3.14, 1)); assert_eq!(g(false, 3.14, 1), (3.14, 1)); @@ -59,8 +59,8 @@ fn main () { // Trying out a real one - assert!(12.test_neq(&10)); - assert!(!10.test_neq(&10)); + //assert!(12.test_neq(&10)); + //assert!(!10.test_neq(&10)); assert!(a.test_neq(&b)); assert!(!a.test_neq(&a)); From f41bae41ebc80b8b922137461df037a6b25fb66b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 25 Jun 2013 19:19:38 -0700 Subject: [PATCH 15/18] librustc: Fix more merge fallout. --- src/libextra/arena.rs | 20 +++++++++++++++----- src/librustc/metadata/decoder.rs | 8 ++++---- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/reachable.rs | 3 ++- src/librustc/middle/resolve.rs | 4 ++-- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/libextra/arena.rs b/src/libextra/arena.rs index 79e09c32030b3..2f18b0562e0fe 100644 --- a/src/libextra/arena.rs +++ b/src/libextra/arena.rs @@ -229,15 +229,25 @@ 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 start; + let end; + let tydesc_start; + let after_tydesc; + + { + let head = transmute_mut_region(&mut self.head); + + tydesc_start = head.fill; + after_tydesc = head.fill + sys::size_of::<*TyDesc>(); + start = round_up_to(after_tydesc, align); + end = start + n_bytes; + } - let tydesc_start = head.fill; - let after_tydesc = head.fill + sys::size_of::<*TyDesc>(); - let start = round_up_to(after_tydesc, align); - let end = start + n_bytes; if end > at_vec::capacity(self.head.data) { return self.alloc_nonpod_grow(n_bytes, align); } + + let head = transmute_mut_region(&mut self.head); head.fill = round_up_to(end, sys::pref_align_of::<*TyDesc>()); //debug!("idx = %u, size = %u, align = %u, fill = %u", diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 263c88017afd9..c50efd12c2f38 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -523,10 +523,10 @@ impl<'self> EachItemContext<'self> { Mod | ForeignMod | Trait | Impl => { continue = self.each_item_of_module(def_id); } - Freeze | Struct | UnsafeFn | Fn | PureFn | ForeignFn | - UnsafeStaticMethod | StaticMethod | PureStaticMethod | Type | - ForeignType | Variant | Enum | PublicField | PrivateField | - InheritedField => {} + ImmStatic | MutStatic | Struct | UnsafeFn | Fn | PureFn | + ForeignFn | UnsafeStaticMethod | StaticMethod | + PureStaticMethod | Type | ForeignType | Variant | Enum | + PublicField | PrivateField | InheritedField => {} } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index f93cb265d785f..52c01fa76476b 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -452,7 +452,7 @@ 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 index fe7eccf9d594a..88bd9c1f6f4aa 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -396,7 +396,8 @@ impl ReachableContext { // 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| { + for self.tcx.destructor_for_type.iter().advance + |(_, destructor_def_id)| { if destructor_def_id.crate == local_crate { self.reachable_symbols.insert(destructor_def_id.node); } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index a1b6132195bdd..6f34bcfdb629e 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -3240,8 +3240,8 @@ impl Resolver { pub fn add_exports_for_module(@mut self, exports2: &mut ~[Export2], module_: @mut Module) { - for module_.import_resolutions.iter().advance |ident, - importresolution| { + for module_.import_resolutions.iter().advance |(ident, + importresolution)| { if importresolution.privacy != Public { debug!("(computing exports) not reexporting private `%s`", self.session.str_of(*ident)); From bbb86495bf894a06e979b935bc6e7895cf3831ce Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 26 Jun 2013 15:54:51 -0700 Subject: [PATCH 16/18] libextra: Fix even more merge fallout. --- src/libextra/ebml.rs | 3 +-- src/libextra/num/bigint.rs | 2 -- src/libextra/test.rs | 3 --- src/libextra/timer.rs | 1 - src/libstd/task/spawn.rs | 1 - 5 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/libextra/ebml.rs b/src/libextra/ebml.rs index 797e00eda1f70..a7e6fbfe26579 100644 --- a/src/libextra/ebml.rs +++ b/src/libextra/ebml.rs @@ -94,12 +94,11 @@ pub mod reader { use serialize; - use core::prelude::*; use core::cast::transmute; use core::int; use core::io; + use core::option::{None, Option, Some}; use core::ptr::offset; - use core::str; use core::unstable::intrinsics::bswap32; use core::vec; diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 0dc966771480a..32e5f59591f80 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -383,8 +383,6 @@ impl Integer for BigUint { while m >= b { 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 diff --git a/src/libextra/test.rs b/src/libextra/test.rs index 61c23f9b4714d..7fc9cfb21fd85 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -751,9 +751,6 @@ impl BenchHarness { } 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/libextra/timer.rs b/src/libextra/timer.rs index 79451db8b1715..e23f9113319d0 100644 --- a/src/libextra/timer.rs +++ b/src/libextra/timer.rs @@ -125,7 +125,6 @@ pub fn recv_timeout(iotask: &IoTask, -> Option { 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/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index da3dc6b2a2e5a..8f06fede05722 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -637,7 +637,6 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { let result: ~fn() = || { // Agh. Get move-mode items into the closure. FIXME (#2829) let (notify_chan, child_arc, ancestors) = child_data.take(); - let mut child_arc = child_arc; let mut ancestors = ancestors; // Child task runs this code. From 2e9cdf416541659f39dc10dcb5e3c9171b09c4d9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 27 Jun 2013 11:16:53 -0700 Subject: [PATCH 17/18] librustc: Fix even *more* merge fallout! --- src/librustc/metadata/decoder.rs | 8 ++++---- src/librustc/middle/ty.rs | 8 ++++---- src/librustc/middle/typeck/astconv.rs | 2 +- src/librustpkg/rustpkg.rs | 1 + 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index c50efd12c2f38..40ca4eaa3294e 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -523,10 +523,10 @@ impl<'self> EachItemContext<'self> { Mod | ForeignMod | Trait | Impl => { continue = self.each_item_of_module(def_id); } - ImmStatic | MutStatic | Struct | UnsafeFn | Fn | PureFn | - ForeignFn | UnsafeStaticMethod | StaticMethod | - PureStaticMethod | Type | ForeignType | Variant | Enum | - PublicField | PrivateField | InheritedField => {} + ImmStatic | MutStatic | Struct | UnsafeFn | Fn | ForeignFn | + UnsafeStaticMethod | StaticMethod | Type | ForeignType | + Variant | Enum | PublicField | PrivateField | + InheritedField => {} } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index a81a4e020c3e2..9c1c01d806874 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2293,11 +2293,11 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { BoundCopy if store == UniqTraitStore => TC_NONCOPY_TRAIT, BoundCopy => TC_NONE, // @Trait/&Trait are copyable either way - BoundStatic if bounds.contains_elem(BoundOwned) - => TC_NONE, // Owned bound implies static bound. + BoundStatic if bounds.contains_elem(BoundSend) + => TC_NONE, // Send bound implies static bound. BoundStatic => TC_BORROWED_POINTER, // Useful for "@Trait:'static" - BoundOwned => TC_NON_OWNED, - BoundConst => TC_MUTABLE, + BoundSend => TC_NON_SENDABLE, + BoundFreeze => TC_MUTABLE, BoundSized => TC_NONE, // don't care if interior is sized }; } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 70df9877162eb..3d0cbec8b1a6c 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -790,7 +790,7 @@ fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option { - let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundOwned); set + let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundSend); set } // @Trait is sugar for @Trait:'static. // &'static Trait is sugar for &'static Trait:'static. diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs index ca13ba39d59c4..550a3411b5ddc 100644 --- a/src/librustpkg/rustpkg.rs +++ b/src/librustpkg/rustpkg.rs @@ -192,6 +192,7 @@ pub trait CtxMethods { fn clean(&self, workspace: &Path, id: &PkgId); fn info(&self); fn install(&self, workspace: &Path, id: &PkgId); + fn install_no_build(&self, workspace: &Path, id: &PkgId); fn prefer(&self, _id: &str, _vers: Option<~str>); fn test(&self); fn uninstall(&self, _id: &str, _vers: Option<~str>); From 2224c6de1e9d238d566dd327a9b8bba440550d6a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 27 Jun 2013 15:07:16 -0700 Subject: [PATCH 18/18] librustc: Fix even *MORE* merge fallout! --- src/librustc/middle/lang_items.rs | 4 ++-- src/libstd/os.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3418fc649da0e..08e55df5b368d 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -295,9 +295,9 @@ impl<'self> LanguageItemCollector<'self> { -> LanguageItemCollector<'a> { let mut item_refs = HashMap::new(); - item_refs.insert(@"const", FreezeTraitLangItem as uint); + item_refs.insert(@"freeze", FreezeTraitLangItem as uint); item_refs.insert(@"copy", CopyTraitLangItem as uint); - item_refs.insert(@"owned", SendTraitLangItem as uint); + item_refs.insert(@"send", SendTraitLangItem as uint); item_refs.insert(@"sized", SizedTraitLangItem as uint); item_refs.insert(@"drop", DropTraitLangItem as uint); diff --git a/src/libstd/os.rs b/src/libstd/os.rs index f76489007d9cb..e54f4f4c54eea 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -146,7 +146,7 @@ pub mod win32 { pub fn as_utf16_p(s: &str, f: &fn(*u16) -> T) -> T { let mut t = s.to_utf16(); // Null terminate before passing on. - t += [0u16]; + t.push(0u16); vec::as_imm_buf(t, |buf, _len| f(buf)) } }