From 45c62c08f9740dfcdf64c64c8b183acfc22fb3d6 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 9 Sep 2013 19:57:08 -0700 Subject: [PATCH 01/21] std: rename Option::unwrap_or_default() to unwrap_or() --- src/compiletest/compiletest.rs | 2 +- src/libextra/glob.rs | 2 +- src/librustc/driver/driver.rs | 6 +++--- src/librustc/middle/privacy.rs | 3 +-- src/librustc/middle/typeck/check/_match.rs | 4 ++-- src/librustdoc/attr_pass.rs | 2 +- src/librustdoc/config.rs | 2 +- src/libstd/at_vec.rs | 2 +- src/libstd/option.rs | 2 +- src/libstd/os.rs | 2 +- src/libstd/vec.rs | 2 +- src/libsyntax/parse/parser.rs | 8 ++++---- 12 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index df0462203a9e..166638bc359b 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -309,7 +309,7 @@ pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName { let filename = path.filename(); let p = path.pop(); let dir = p.filename(); - fmt!("%s/%s", dir.unwrap_or_default(""), filename.unwrap_or_default("")) + fmt!("%s/%s", dir.unwrap_or(""), filename.unwrap_or("")) } test::DynTestName(fmt!("[%s] %s", diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs index 07386b41caac..984a09aed3e3 100644 --- a/src/libextra/glob.rs +++ b/src/libextra/glob.rs @@ -312,7 +312,7 @@ impl Pattern { let require_literal = |c| { (options.require_literal_separator && is_sep(c)) || (options.require_literal_leading_dot && c == '.' - && is_sep(prev_char.unwrap_or_default('/'))) + && is_sep(prev_char.unwrap_or('/'))) }; for (ti, token) in self.tokens.slice_from(i).iter().enumerate() { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 0fd93d65b70b..1841e25ee95e 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -681,9 +681,9 @@ pub fn build_session_options(binary: @str, link::output_type_bitcode } else { link::output_type_exe }; let sysroot_opt = getopts::opt_maybe_str(matches, "sysroot").map_move(|m| @Path(m)); - let target = getopts::opt_maybe_str(matches, "target").unwrap_or_default(host_triple()); - let target_cpu = getopts::opt_maybe_str(matches, "target-cpu").unwrap_or_default(~"generic"); - let target_feature = getopts::opt_maybe_str(matches, "target-feature").unwrap_or_default(~""); + let target = getopts::opt_maybe_str(matches, "target").unwrap_or(host_triple()); + let target_cpu = getopts::opt_maybe_str(matches, "target-cpu").unwrap_or(~"generic"); + let target_feature = getopts::opt_maybe_str(matches, "target-feature").unwrap_or(~""); let save_temps = getopts::opt_present(matches, "save-temps"); let opt_level = { if (debugging_opts & session::no_opt) != 0 { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index b6b03d8369a4..51fe2acc72ad 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -221,8 +221,7 @@ impl PrivacyVisitor { // If the method is a default method, we need to use the def_id of // the default implementation. // Having to do this this is really unfortunate. - let method_id = ty::method(self.tcx, method_id).provided_source - .unwrap_or_default(method_id); + let method_id = ty::method(self.tcx, method_id).provided_source.unwrap_or(method_id); if method_id.crate == LOCAL_CRATE { let is_private = self.method_is_private(span, method_id.node); diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 196057e09f76..f08694e44371 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -173,7 +173,7 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::Pat, path: &ast::Path, fcx.write_error(pat.id); kind_name = "[error]"; arg_types = (*subpats).clone() - .unwrap_or_default(~[]) + .unwrap_or(~[]) .map(|_| ty::mk_err()); } } @@ -222,7 +222,7 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::Pat, path: &ast::Path, fcx.write_error(pat.id); kind_name = "[error]"; arg_types = (*subpats).clone() - .unwrap_or_default(~[]) + .unwrap_or(~[]) .map(|_| ty::mk_err()); } } diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs index 2e7c73d34215..bd8d9a65cd33 100644 --- a/src/librustdoc/attr_pass.rs +++ b/src/librustdoc/attr_pass.rs @@ -68,7 +68,7 @@ fn fold_crate( doc::CrateDoc { topmod: doc::ModDoc { item: doc::ItemDoc { - name: attrs.name.clone().unwrap_or_default(doc.topmod.name_()), + name: attrs.name.clone().unwrap_or(doc.topmod.name_()), .. doc.topmod.item.clone() }, .. doc.topmod.clone() diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index e6d80e1443bb..c8dd38394c96 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -142,7 +142,7 @@ fn config_from_opts( let output_dir = getopts::opt_maybe_str(matches, opt_output_dir()); let output_dir = output_dir.map_move(|s| Path(s)); result::Ok(Config { - output_dir: output_dir.unwrap_or_default(config.output_dir.clone()), + output_dir: output_dir.unwrap_or(config.output_dir.clone()), .. config }) }; diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index a4e841f98f80..ce8e90e1a432 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -45,7 +45,7 @@ pub fn capacity(v: @[T]) -> uint { #[inline] pub fn build(size: Option, builder: &fn(push: &fn(v: A))) -> @[A] { let mut vec = @[]; - unsafe { raw::reserve(&mut vec, size.unwrap_or_default(4)); } + unsafe { raw::reserve(&mut vec, size.unwrap_or(4)); } builder(|x| unsafe { raw::push(&mut vec, x) }); vec } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index b72046cce721..5ac6fcda0433 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -332,7 +332,7 @@ impl Option { /// Returns the contained value or a default #[inline] - pub fn unwrap_or_default(self, def: T) -> T { + pub fn unwrap_or(self, def: T) -> T { match self { Some(x) => x, None => def diff --git a/src/libstd/os.rs b/src/libstd/os.rs index ab1210aabadc..95a75b849233 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -611,7 +611,7 @@ pub fn tmpdir() -> Path { if cfg!(target_os = "android") { Path("/data/tmp") } else { - getenv_nonempty("TMPDIR").unwrap_or_default(Path("/tmp")) + getenv_nonempty("TMPDIR").unwrap_or(Path("/tmp")) } } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 1ff583518865..55b8e3769ea0 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -205,7 +205,7 @@ pub fn with_capacity(capacity: uint) -> ~[T] { */ #[inline] pub fn build(size: Option, builder: &fn(push: &fn(v: A))) -> ~[A] { - let mut vec = with_capacity(size.unwrap_or_default(4)); + let mut vec = with_capacity(size.unwrap_or(4)); builder(|x| vec.push(x)); vec } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b5772a9eede2..8725a0426f72 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -802,7 +802,7 @@ impl Parser { */ let opt_abis = self.parse_opt_abis(); - let abis = opt_abis.unwrap_or_default(AbiSet::Rust()); + let abis = opt_abis.unwrap_or(AbiSet::Rust()); let purity = self.parse_unsafety(); self.expect_keyword(keywords::Fn); let (decl, lifetimes) = self.parse_ty_fn_decl(); @@ -3461,7 +3461,7 @@ impl Parser { let ident = self.parse_ident(); let opt_bounds = self.parse_optional_ty_param_bounds(); // For typarams we don't care about the difference b/w "" and "". - let bounds = opt_bounds.unwrap_or_default(opt_vec::Empty); + let bounds = opt_bounds.unwrap_or(opt_vec::Empty); ast::TyParam { ident: ident, id: ast::DUMMY_NODE_ID, bounds: bounds } } @@ -4363,7 +4363,7 @@ impl Parser { self.obsolete(*self.last_span, ObsoleteExternVisibility); } - let abis = opt_abis.unwrap_or_default(AbiSet::C()); + let abis = opt_abis.unwrap_or(AbiSet::C()); let (inner, next) = self.parse_inner_attrs_and_next(); let m = self.parse_foreign_mod_items(sort, abis, next); @@ -4640,7 +4640,7 @@ impl Parser { if self.eat_keyword(keywords::Fn) { // EXTERN FUNCTION ITEM - let abis = opt_abis.unwrap_or_default(AbiSet::C()); + let abis = opt_abis.unwrap_or(AbiSet::C()); let (ident, item_, extra_attrs) = self.parse_item_fn(extern_fn, abis); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, From 653400a7f0567ed1697ea9181132f7aaca5b2aae Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 9 Sep 2013 19:28:05 -0700 Subject: [PATCH 02/21] std: add default implementations to HashMap --- src/libstd/hashmap.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index fab8299f7a75..2b12564281a5 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -18,6 +18,7 @@ use container::{Container, Mutable, Map, MutableMap, Set, MutableSet}; use clone::Clone; use cmp::{Eq, Equiv}; +use default::Default; use hash::Hash; use iter::{Iterator, FromIterator, Extendable}; use iter::{FilterMap, Chain, Repeat, Zip}; @@ -622,6 +623,10 @@ impl Extendable<(K, V)> for HashMap { } } +impl Default for HashMap { + fn default() -> HashMap { HashMap::new() } +} + /// An implementation of a hash set using the underlying representation of a /// HashMap where the value is (). As with the `HashMap` type, a `HashSet` /// requires that the elements implement the `Eq` and `Hash` traits. @@ -770,6 +775,10 @@ impl Extendable for HashSet { } } +impl Default for HashSet { + fn default() -> HashSet { HashSet::new() } +} + // `Repeat` is used to feed the filter closure an explicit capture // of a reference to the other set /// Set operations iterator From 4a73c8eac7660735822f7d43ac8be2b40b2e1d93 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 9 Sep 2013 19:29:11 -0700 Subject: [PATCH 03/21] std: add default implementations to Option --- src/libstd/option.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 5ac6fcda0433..1f3a31a403cb 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -43,6 +43,7 @@ let unwrapped_msg = match msg { use clone::Clone; use cmp::{Eq,Ord}; +use default::Default; use util; use num::Zero; use iter; @@ -349,6 +350,10 @@ impl Option { } } +impl Default for Option { + fn default() -> Option { None } +} + impl Option { /// Returns the contained value or zero (for this type) #[inline] From f1374a7044d844fb1f89b651bf4c628ac32ed48a Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 9 Sep 2013 19:29:31 -0700 Subject: [PATCH 04/21] libsyntax: add Default implementation to OptVec --- src/libsyntax/opt_vec.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index 2d7801a22ded..46940d2d4dae 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -140,6 +140,10 @@ impl Eq for OptVec { } } +impl Default for OptVec { + fn default() -> OptVec { Empty } +} + pub struct OptVecIterator<'self, T> { priv iter: Option> } From e6c11313c88574aa2500df2f76c5534fbc2e0512 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 9 Sep 2013 19:32:32 -0700 Subject: [PATCH 05/21] std: Add Option.{result_or_default,or_default} that uses Default --- src/librustc/middle/typeck/check/_match.rs | 4 ++-- src/libstd/option.rs | 20 ++++++++++++++++++++ src/libsyntax/parse/parser.rs | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index f08694e44371..061921e60e12 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -173,7 +173,7 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::Pat, path: &ast::Path, fcx.write_error(pat.id); kind_name = "[error]"; arg_types = (*subpats).clone() - .unwrap_or(~[]) + .unwrap_or_default() .map(|_| ty::mk_err()); } } @@ -222,7 +222,7 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::Pat, path: &ast::Path, fcx.write_error(pat.id); kind_name = "[error]"; arg_types = (*subpats).clone() - .unwrap_or(~[]) + .unwrap_or_default() .map(|_| ty::mk_err()); } } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 1f3a31a403cb..84d8a3aa1889 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -350,6 +350,26 @@ impl Option { } } +impl Option { + /// Returns the contained value or default (for this type) + #[inline] + pub fn unwrap_or_default(self) -> T { + match self { + Some(x) => x, + None => Default::default() + } + } + + /// Returns self or `Some`-wrapped default value + #[inline] + pub fn or_default(self) -> Option { + match self { + None => Some(Default::default()), + x => x, + } + } +} + impl Default for Option { fn default() -> Option { None } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8725a0426f72..6a15641430fb 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3461,7 +3461,7 @@ impl Parser { let ident = self.parse_ident(); let opt_bounds = self.parse_optional_ty_param_bounds(); // For typarams we don't care about the difference b/w "" and "". - let bounds = opt_bounds.unwrap_or(opt_vec::Empty); + let bounds = opt_bounds.unwrap_or_default(); ast::TyParam { ident: ident, id: ast::DUMMY_NODE_ID, bounds: bounds } } From 2bd87ad432901f3baeab2fc1f2aa8aa328f04ea7 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 9 Sep 2013 19:32:56 -0700 Subject: [PATCH 06/21] std: Add Default implementation for vecs --- src/libstd/vec.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 55b8e3769ea0..b91384f0ba50 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -104,6 +104,7 @@ use clone::{Clone, DeepClone}; use container::{Container, Mutable}; use cmp::{Eq, TotalOrd, Ordering, Less, Equal, Greater}; use cmp; +use default::Default; use iter::*; use libc::c_void; use num::{Integer, Zero, CheckedAdd, Saturating}; @@ -2236,6 +2237,19 @@ impl DeepClone for ~[A] { } } +// This works because every lifetime is a sub-lifetime of 'static +impl<'self, A> Default for &'self [A] { + fn default() -> &'self [A] { &'self [] } +} + +impl Default for ~[A] { + fn default() -> ~[A] { ~[] } +} + +impl Default for @[A] { + fn default() -> @[A] { @[] } +} + // This works because every lifetime is a sub-lifetime of 'static impl<'self, A> Zero for &'self [A] { fn zero() -> &'self [A] { &'self [] } From 7380b1ce7f7538ca6f6f61cc442f45e64622b902 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 10 Sep 2013 19:03:35 -0700 Subject: [PATCH 07/21] std: Add Option.unwrap_or_else and a couple tests --- src/libstd/option.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 84d8a3aa1889..55d5cb279238 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -340,6 +340,15 @@ impl Option { } } + /// Returns the contained value or computes it from a closure + #[inline] + pub fn unwrap_or_else(self, f: &fn() -> T) -> T { + match self { + Some(x) => x, + None => f() + } + } + /// Applies a function zero or more times until the result is `None`. #[inline] pub fn while_some(self, blk: &fn(v: T) -> Option) { @@ -514,6 +523,44 @@ mod tests { assert_eq!(i, 11); } + #[test] + fn test_unwrap() { + assert_eq!(Some(1).unwrap(), 1); + assert_eq!(Some(~"hello").unwrap(), ~"hello"); + } + + #[test] + #[should_fail] + fn test_unwrap_fail1() { + let x: Option = None; + x.unwrap(); + } + + #[test] + #[should_fail] + fn test_unwrap_fail2() { + let x: Option<~str> = None; + x.unwrap(); + } + + #[test] + fn test_unwrap_or() { + let x: Option = Some(1); + assert_eq!(x.unwrap_or(2), 1); + + let x: Option = None; + assert_eq!(x.unwrap_or(2), 2); + } + + #[test] + fn test_unwrap_or_else() { + let x: Option = Some(1); + assert_eq!(x.unwrap_or_else(|| 2), 1); + + let x: Option = None; + assert_eq!(x.unwrap_or_else(|| 2), 2); + } + #[test] fn test_unwrap_or_zero() { let some_stuff = Some(42); From d625d4a5987b1299441e4a02a8094033587129cb Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 09:00:27 -0700 Subject: [PATCH 08/21] std: Add Option.{and,and_then,or,or_else} --- src/libextra/num/bigint.rs | 4 +- src/libstd/option.rs | 89 ++++++++++++++++++++++++++++++++++---- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 8975ed7fd961..24f44c8a2a8e 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -635,7 +635,7 @@ impl BigUint { // Converts this BigUint into an int, unless it would overflow. pub fn to_int_opt(&self) -> Option { - self.to_uint_opt().chain(|n| { + self.to_uint_opt().and_then(|n| { // If top bit of uint is set, it's too large to convert to // int. if (n >> (2*BigDigit::bits - 1) != 0) { @@ -1221,7 +1221,7 @@ impl BigInt { match self.sign { Plus => self.data.to_int_opt(), Zero => Some(0), - Minus => self.data.to_uint_opt().chain(|n| { + Minus => self.data.to_uint_opt().and_then(|n| { let m: uint = 1 << (2*BigDigit::bits-1); if (n > m) { None diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 55d5cb279238..761ad71a2699 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -127,22 +127,51 @@ impl Option { #[inline] pub fn is_some(&self) -> bool { !self.is_none() } - /// Update an optional value by optionally running its content through a - /// function that returns an option. + /// Returns `None` if the option is `None`, otherwise returns `optb`. #[inline] - pub fn chain(self, f: &fn(t: T) -> Option) -> Option { + pub fn and(self, optb: Option) -> Option { match self { - Some(t) => f(t), - None => None + Some(_) => optb, + None => None, + } + } + + /// Returns `None` if the option is `None`, otherwise calls and returns the + /// value of `f`. + #[inline] + pub fn and_then(self, f: &fn() -> Option) -> Option { + match self { + Some(_) => f(), + None => None, } } - /// Returns the leftmost Some() value, or None if both are None. + /// Returns the option if it contains a value, otherwise returns `optb`. #[inline] pub fn or(self, optb: Option) -> Option { match self { - Some(opta) => Some(opta), - _ => optb + Some(_) => self, + None => optb + } + } + + /// Returns the option if it contains a value, otherwise calls and returns the + /// value of `f`. + #[inline] + pub fn or_else(self, f: &fn() -> Option) -> Option { + match self { + Some(_) => self, + None => f(), + } + } + + /// Update an optional value by optionally running its content through a + /// function that returns an option. + #[inline] + pub fn chain(self, f: &fn(T) -> Option) -> Option { + match self { + Some(t) => f(t), + None => None } } @@ -509,6 +538,50 @@ mod tests { let _y3 = y.take_unwrap(); } + #[test] + fn test_and() { + let x: Option = Some(1); + assert_eq!(x.and(Some(2)), Some(2)); + assert_eq!(x.and(None), None); + + let x: Option = None; + assert_eq!(x.and(Some(2)), None); + assert_eq!(x.and(None), None); + } + + #[test] + fn test_and_then() { + let x: Option = Some(1); + assert_eq!(x.and_then(|| Some(2)), Some(2)); + assert_eq!(x.and_then(|| None), None); + + let x: Option = None; + assert_eq!(x.and_then(|| Some(2)), None); + assert_eq!(x.and_then(|| None), None); + } + + #[test] + fn test_or() { + let x: Option = Some(1); + assert_eq!(x.or(Some(2)), Some(1)); + assert_eq!(x.or(None), Some(1)); + + let x: Option = None; + assert_eq!(x.or(Some(2)), Some(2)); + assert_eq!(x.or(None), None); + } + + #[test] + fn test_or_else() { + let x: Option = Some(1); + assert_eq!(x.or_else(|| Some(2)), Some(1)); + assert_eq!(x.or_else(|| None), Some(1)); + + let x: Option = None; + assert_eq!(x.or_else(|| Some(2)), Some(2)); + assert_eq!(x.or_else(|| None), None); + } + #[test] fn test_option_while_some() { let mut i = 0; From b8a284e873125097dcfa5cec5d7135789d6673b3 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 10 Sep 2013 21:16:59 -0700 Subject: [PATCH 09/21] std: fix a warning --- src/libstd/to_bytes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs index 855cdfcb8517..f47468e1ef8c 100644 --- a/src/libstd/to_bytes.rs +++ b/src/libstd/to_bytes.rs @@ -383,5 +383,5 @@ mod test { #[test] fn iterbytes_compiles () { takes_iterbytes((3,4,5,false)); } - fn takes_iterbytes(x : T) {} + fn takes_iterbytes(_x : T) {} } From ff34740a29e3ba4f8c34fd05badf798e481e2257 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 09:26:59 -0700 Subject: [PATCH 10/21] std: Add ToOption/IntoOption/AsOption --- src/libstd/either.rs | 60 ++++++++++++++++++++++++++++++++++++++++ src/libstd/option.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++ src/libstd/result.rs | 60 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) diff --git a/src/libstd/either.rs b/src/libstd/either.rs index ec9e6d1ca4bc..1773a6f8a977 100644 --- a/src/libstd/either.rs +++ b/src/libstd/either.rs @@ -13,6 +13,7 @@ #[allow(missing_doc)]; use option::{Some, None}; +use option; use clone::Clone; use container::Container; use cmp::Eq; @@ -116,6 +117,36 @@ impl Either { } } +impl option::ToOption for Either { + #[inline] + fn to_option(&self)-> option::Option { + match *self { + Left(_) => None, + Right(ref r) => Some(r.clone()), + } + } +} + +impl option::IntoOption for Either { + #[inline] + fn into_option(self)-> option::Option { + match self { + Left(_) => None, + Right(r) => Some(r), + } + } +} + +impl option::AsOption for Either { + #[inline] + fn as_option<'a>(&'a self) -> option::Option<&'a R> { + match *self { + Left(_) => None, + Right(ref r) => Some(r), + } + } +} + /// An iterator yielding the `Left` values of its source pub type Lefts = FilterMap<'static, Either, L, Iter>; @@ -167,6 +198,9 @@ pub fn partition(eithers: ~[Either]) -> (~[L], ~[R]) { mod tests { use super::*; + use option::{IntoOption, ToOption, AsOption}; + use option; + #[test] fn test_either_left() { let val = Left(10); @@ -260,4 +294,30 @@ mod tests { assert_eq!(rights.len(), 0u); } + #[test] + pub fn test_to_option() { + let right: Either = Right(100); + let left: Either = Left(404); + + assert_eq!(right.to_option(), option::Some(100)); + assert_eq!(left.to_option(), option::None); + } + + #[test] + pub fn test_into_option() { + let right: Either = Right(100); + let left: Either = Left(404); + + assert_eq!(right.into_option(), option::Some(100)); + assert_eq!(left.into_option(), option::None); + } + + #[test] + pub fn test_as_option() { + let right: Either = Right(100); + let left: Either = Left(404); + + assert_eq!(right.as_option().unwrap(), &100); + assert_eq!(left.as_option(), option::None); + } } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 761ad71a2699..5107076546a5 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -388,6 +388,44 @@ impl Option { } } +/// A generic trait for converting a value to a `Option` +pub trait ToOption { + /// Convert to the `option` type + fn to_option(&self) -> Option; +} + +/// A generic trait for converting a value to a `Option` +pub trait IntoOption { + /// Convert to the `option` type + fn into_option(self) -> Option; +} + +/// A generic trait for converting a value to a `Option` +pub trait AsOption { + /// Convert to the `option` type + fn as_option<'a>(&'a self) -> Option<&'a T>; +} + +impl ToOption for Option { + #[inline] + fn to_option(&self) -> Option { self.clone() } +} + +impl IntoOption for Option { + #[inline] + fn into_option(self) -> Option { self } +} + +impl AsOption for Option { + #[inline] + fn as_option<'a>(&'a self) -> Option<&'a T> { + match *self { + Some(ref x) => Some(x), + None => None, + } + } +} + impl Option { /// Returns the contained value or default (for this type) #[inline] @@ -711,4 +749,31 @@ mod tests { assert!(!x.mutate_default(0i, |i| i+1)); assert_eq!(x, Some(0i)); } + + #[test] + pub fn test_to_option() { + let some: Option = Some(100); + let none: Option = None; + + assert_eq!(some.to_option(), Some(100)); + assert_eq!(none.to_option(), None); + } + + #[test] + pub fn test_into_option() { + let some: Option = Some(100); + let none: Option = None; + + assert_eq!(some.into_option(), Some(100)); + assert_eq!(none.into_option(), None); + } + + #[test] + pub fn test_as_option() { + let some: Option = Some(100); + let none: Option = None; + + assert_eq!(some.as_option().unwrap(), &100); + assert_eq!(none.as_option(), None); + } } diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 793086dca78d..d72f151baee1 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -17,6 +17,7 @@ use cmp::Eq; use either; use iter::Iterator; use option::{None, Option, Some, OptionIterator}; +use option; use vec; use vec::OwnedVector; use to_str::ToStr; @@ -255,6 +256,36 @@ impl Result { } } +impl option::ToOption for Result { + #[inline] + fn to_option(&self)-> Option { + match *self { + Ok(ref t) => Some(t.clone()), + Err(_) => None, + } + } +} + +impl option::IntoOption for Result { + #[inline] + fn into_option(self)-> Option { + match self { + Ok(t) => Some(t), + Err(_) => None, + } + } +} + +impl option::AsOption for Result { + #[inline] + fn as_option<'a>(&'a self)-> Option<&'a T> { + match *self { + Ok(ref t) => Some(t), + Err(_) => None, + } + } +} + #[inline] #[allow(missing_doc)] pub fn map_opt(o_t: &Option, @@ -336,6 +367,8 @@ mod tests { use either; use iter::range; + use option::{IntoOption, ToOption, AsOption}; + use option; use str::OwnedStr; use vec::ImmutableVector; @@ -460,4 +493,31 @@ mod tests { .map(|f| (*f)())), Err(1)); } + + #[test] + pub fn test_to_option() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + assert_eq!(ok.to_option(), option::Some(100)); + assert_eq!(err.to_option(), option::None); + } + + #[test] + pub fn test_into_option() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + assert_eq!(ok.into_option(), option::Some(100)); + assert_eq!(err.into_option(), option::None); + } + + #[test] + pub fn test_as_option() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + assert_eq!(ok.as_option().unwrap(), &100); + assert_eq!(err.as_option(), option::None); + } } From 12e0d7ecf061313d02a4647db8c1b30aad2ae53d Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 09:32:09 -0700 Subject: [PATCH 11/21] std: Add ToResult/IntoResult/AsResult --- src/libstd/either.rs | 74 +++++++++++++++++++++++++++++++++++++------- src/libstd/option.rs | 41 ++++++++++++++++++++++++ src/libstd/result.rs | 68 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 12 deletions(-) diff --git a/src/libstd/either.rs b/src/libstd/either.rs index 1773a6f8a977..526a5380dfbe 100644 --- a/src/libstd/either.rs +++ b/src/libstd/either.rs @@ -54,18 +54,6 @@ impl Either { } } - /// Converts a `Either` to a `Result` - /// - /// Converts an `Either` type to a `Result` type, making the "right" choice - /// an `Ok` result, and the "left" choice a `Err` - #[inline] - pub fn to_result(self) -> Result { - match self { - Right(r) => result::Ok(r), - Left(l) => result::Err(l) - } - } - /// Checks whether the given value is a `Left` #[inline] pub fn is_left(&self) -> bool { @@ -147,6 +135,36 @@ impl option::AsOption for Either { } } +impl result::ToResult for Either { + #[inline] + fn to_result(&self)-> result::Result { + match *self { + Left(ref l) => result::Err(l.clone()), + Right(ref r) => result::Ok(r.clone()), + } + } +} + +impl result::IntoResult for Either { + #[inline] + fn into_result(self)-> result::Result { + match self { + Left(l) => result::Err(l), + Right(r) => result::Ok(r), + } + } +} + +impl result::AsResult for Either { + #[inline] + fn as_result<'a>(&'a self) -> result::Result<&'a R, &'a L> { + match *self { + Left(ref l) => result::Err(l), + Right(ref r) => result::Ok(r), + } + } +} + /// An iterator yielding the `Left` values of its source pub type Lefts = FilterMap<'static, Either, L, Iter>; @@ -200,6 +218,8 @@ mod tests { use option::{IntoOption, ToOption, AsOption}; use option; + use result::{IntoResult, ToResult, AsResult}; + use result; #[test] fn test_either_left() { @@ -320,4 +340,34 @@ mod tests { assert_eq!(right.as_option().unwrap(), &100); assert_eq!(left.as_option(), option::None); } + + #[test] + pub fn test_to_result() { + let right: Either = Right(100); + let left: Either = Left(404); + + assert_eq!(right.to_result(), result::Ok(100)); + assert_eq!(left.to_result(), result::Err(404)); + } + + #[test] + pub fn test_into_result() { + let right: Either = Right(100); + let left: Either = Left(404); + + assert_eq!(right.into_result(), result::Ok(100)); + assert_eq!(left.into_result(), result::Err(404)); + } + + #[test] + pub fn test_as_result() { + let right: Either = Right(100); + let left: Either = Left(404); + + let x = 100; + assert_eq!(right.as_result(), result::Ok(&x)); + + let x = 404; + assert_eq!(left.as_result(), result::Err(&x)); + } } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 5107076546a5..83bc7856098e 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -48,6 +48,7 @@ use util; use num::Zero; use iter; use iter::{Iterator, DoubleEndedIterator, ExactSize}; +use result; use str::{StrSlice, OwnedStr}; use to_str::ToStr; use clone::DeepClone; @@ -426,6 +427,26 @@ impl AsOption for Option { } } +impl result::ToResult for Option { + #[inline] + fn to_result(&self) -> result::Result { + match *self { + Some(ref x) => result::Ok(x.clone()), + None => result::Err(()), + } + } +} + +impl result::IntoResult for Option { + #[inline] + fn into_result(self) -> result::Result { + match self { + Some(x) => result::Ok(x), + None => result::Err(()), + } + } +} + impl Option { /// Returns the contained value or default (for this type) #[inline] @@ -508,6 +529,8 @@ impl ExactSize for OptionIterator {} #[cfg(test)] mod tests { use super::*; + use result::{IntoResult, ToResult}; + use result; use util; #[test] @@ -776,4 +799,22 @@ mod tests { assert_eq!(some.as_option().unwrap(), &100); assert_eq!(none.as_option(), None); } + + #[test] + pub fn test_to_result() { + let some: Option = Some(100); + let none: Option = None; + + assert_eq!(some.to_result(), result::Ok(100)); + assert_eq!(none.to_result(), result::Err(())); + } + + #[test] + pub fn test_into_result() { + let some: Option = Some(100); + let none: Option = None; + + assert_eq!(some.into_result(), result::Ok(100)); + assert_eq!(none.into_result(), result::Err(())); + } } diff --git a/src/libstd/result.rs b/src/libstd/result.rs index d72f151baee1..f6c2a39ccf09 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -256,6 +256,24 @@ impl Result { } } +/// A generic trait for converting a value to a `Result` +pub trait ToResult { + /// Convert to the `result` type + fn to_result(&self) -> Result; +} + +/// A generic trait for converting a value to a `Result` +pub trait IntoResult { + /// Convert to the `result` type + fn into_result(self) -> Result; +} + +/// A generic trait for converting a value to a `Result` +pub trait AsResult { + /// Convert to the `result` type + fn as_result<'a>(&'a self) -> Result<&'a T, &'a E>; +} + impl option::ToOption for Result { #[inline] fn to_option(&self)-> Option { @@ -286,6 +304,26 @@ impl option::AsOption for Result { } } +impl ToResult for Result { + #[inline] + fn to_result(&self) -> Result { self.clone() } +} + +impl IntoResult for Result { + #[inline] + fn into_result(self) -> Result { self } +} + +impl AsResult for Result { + #[inline] + fn as_result<'a>(&'a self) -> Result<&'a T, &'a E> { + match *self { + Ok(ref t) => Ok(t), + Err(ref e) => Err(e), + } + } +} + #[inline] #[allow(missing_doc)] pub fn map_opt(o_t: &Option, @@ -520,4 +558,34 @@ mod tests { assert_eq!(ok.as_option().unwrap(), &100); assert_eq!(err.as_option(), option::None); } + + #[test] + pub fn test_to_result() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + assert_eq!(ok.to_result(), Ok(100)); + assert_eq!(err.to_result(), Err(404)); + } + + #[test] + pub fn test_into_result() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + assert_eq!(ok.into_result(), Ok(100)); + assert_eq!(err.into_result(), Err(404)); + } + + #[test] + pub fn test_as_result() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + let x = 100; + assert_eq!(ok.as_result(), Ok(&x)); + + let x = 404; + assert_eq!(err.as_result(), Err(&x)); + } } From e03d60e9ebf2dbc2d18ab9919f905c17b967fcde Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 09:33:45 -0700 Subject: [PATCH 12/21] std: Add ToEither/IntoEither/AsEither --- src/libstd/either.rs | 62 ++++++++++++++++++++++++++++++++++ src/libstd/option.rs | 42 +++++++++++++++++++++++ src/libstd/result.rs | 79 ++++++++++++++++++++++++++++++++------------ 3 files changed, 162 insertions(+), 21 deletions(-) diff --git a/src/libstd/either.rs b/src/libstd/either.rs index 526a5380dfbe..27381f64ad4a 100644 --- a/src/libstd/either.rs +++ b/src/libstd/either.rs @@ -105,6 +105,24 @@ impl Either { } } +/// A generic trait for converting a value to a `Either` +pub trait ToEither { + /// Convert to the `either` type + fn to_either(&self) -> Either; +} + +/// A generic trait for converting a value to a `Either` +pub trait IntoEither { + /// Convert to the `either` type + fn into_either(self) -> Either; +} + +/// A generic trait for converting a value to a `Either` +pub trait AsEither { + /// Convert to the `either` type + fn as_either<'a>(&'a self) -> Either<&'a L, &'a R>; +} + impl option::ToOption for Either { #[inline] fn to_option(&self)-> option::Option { @@ -165,6 +183,23 @@ impl result::AsResult for Either { } } +impl ToEither for Either { + fn to_either(&self) -> Either { self.clone() } +} + +impl IntoEither for Either { + fn into_either(self) -> Either { self } +} + +impl AsEither for Either { + fn as_either<'a>(&'a self) -> Either<&'a L, &'a R> { + match *self { + Left(ref l) => Left(l), + Right(ref r) => Right(r), + } + } +} + /// An iterator yielding the `Left` values of its source pub type Lefts = FilterMap<'static, Either, L, Iter>; @@ -370,4 +405,31 @@ mod tests { let x = 404; assert_eq!(left.as_result(), result::Err(&x)); } + + #[test] + pub fn test_to_either() { + let right: Either = Right(100); + let left: Either = Left(404); + + assert_eq!(right.to_either(), Right(100)); + assert_eq!(left.to_either(), Left(404)); + } + + #[test] + pub fn test_into_either() { + let right: Either = Right(100); + let left: Either = Left(404); + + assert_eq!(right.into_either(), Right(100)); + assert_eq!(left.into_either(), Left(404)); + } + + #[test] + pub fn test_as_either() { + let right: Either = Right(100); + let left: Either = Left(404); + + assert_eq!(right.as_either().unwrap_right(), &100); + assert_eq!(left.as_either().unwrap_left(), &404); + } } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 83bc7856098e..cd9e39807160 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -44,6 +44,7 @@ let unwrapped_msg = match msg { use clone::Clone; use cmp::{Eq,Ord}; use default::Default; +use either; use util; use num::Zero; use iter; @@ -447,6 +448,26 @@ impl result::IntoResult for Option { } } +impl either::ToEither<(), T> for Option { + #[inline] + fn to_either(&self) -> either::Either<(), T> { + match *self { + Some(ref x) => either::Right(x.clone()), + None => either::Left(()), + } + } +} + +impl either::IntoEither<(), T> for Option { + #[inline] + fn into_either(self) -> either::Either<(), T> { + match self { + Some(x) => either::Right(x), + None => either::Left(()), + } + } +} + impl Option { /// Returns the contained value or default (for this type) #[inline] @@ -529,6 +550,9 @@ impl ExactSize for OptionIterator {} #[cfg(test)] mod tests { use super::*; + + use either::{IntoEither, ToEither}; + use either; use result::{IntoResult, ToResult}; use result; use util; @@ -817,4 +841,22 @@ mod tests { assert_eq!(some.into_result(), result::Ok(100)); assert_eq!(none.into_result(), result::Err(())); } + + #[test] + pub fn test_to_either() { + let some: Option = Some(100); + let none: Option = None; + + assert_eq!(some.to_either(), either::Right(100)); + assert_eq!(none.to_either(), either::Left(())); + } + + #[test] + pub fn test_into_either() { + let some: Option = Some(100); + let none: Option = None; + + assert_eq!(some.into_either(), either::Right(100)); + assert_eq!(none.into_either(), either::Left(())); + } } diff --git a/src/libstd/result.rs b/src/libstd/result.rs index f6c2a39ccf09..20b65f1576d7 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -37,18 +37,6 @@ pub enum Result { } impl Result { - /// Convert to the `either` type - /// - /// `Ok` result variants are converted to `either::Right` variants, `Err` - /// result variants are converted to `either::Left`. - #[inline] - pub fn to_either(self)-> either::Either{ - match self { - Ok(t) => either::Right(t), - Err(e) => either::Left(e), - } - } - /// Get a reference to the value out of a successful result /// /// # Failure @@ -324,6 +312,36 @@ impl AsResult for Result { } } +impl either::ToEither for Result { + #[inline] + fn to_either(&self)-> either::Either { + match *self { + Ok(ref t) => either::Right(t.clone()), + Err(ref e) => either::Left(e.clone()), + } + } +} + +impl either::IntoEither for Result { + #[inline] + fn into_either(self)-> either::Either { + match self { + Ok(t) => either::Right(t), + Err(e) => either::Left(e), + } + } +} + +impl either::AsEither for Result { + #[inline] + fn as_either<'a>(&'a self)-> either::Either<&'a E, &'a T> { + match *self { + Ok(ref t) => either::Right(t), + Err(ref e) => either::Left(e), + } + } +} + #[inline] #[allow(missing_doc)] pub fn map_opt(o_t: &Option, @@ -403,6 +421,7 @@ pub fn fold_>>( mod tests { use super::*; + use either::{IntoEither, ToEither, AsEither}; use either; use iter::range; use option::{IntoOption, ToOption, AsOption}; @@ -483,15 +502,6 @@ mod tests { assert_eq!(*foo.get_ref(), 100); } - #[test] - pub fn test_to_either() { - let r: Result = Ok(100); - let err: Result<(), int> = Err(404); - - assert_eq!(r.to_either(), either::Right(100)); - assert_eq!(err.to_either(), either::Left(404)); - } - #[test] fn test_collect() { assert_eq!(collect(range(0, 0) @@ -588,4 +598,31 @@ mod tests { let x = 404; assert_eq!(err.as_result(), Err(&x)); } + + #[test] + pub fn test_to_either() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + assert_eq!(ok.to_either(), either::Right(100)); + assert_eq!(err.to_either(), either::Left(404)); + } + + #[test] + pub fn test_into_either() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + assert_eq!(ok.into_either(), either::Right(100)); + assert_eq!(err.into_either(), either::Left(404)); + } + + #[test] + pub fn test_as_either() { + let ok: Result = Ok(100); + let err: Result = Err(404); + + assert_eq!(ok.as_either().unwrap_right(), &100); + assert_eq!(err.as_either().unwrap_left(), &404); + } } From 38f97ea10313ba9a8c6f57fbf73ff8daf5376e8b Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 12:52:17 -0700 Subject: [PATCH 13/21] std: Rename {Option,Result}::chain{,_err}* to {and_then,or_else} --- src/libextra/num/rational.rs | 8 +-- src/libextra/time.rs | 64 ++++++++++---------- src/librustc/driver/driver.rs | 2 +- src/librustc/front/config.rs | 4 +- src/librustc/metadata/creader.rs | 2 +- src/librustc/metadata/decoder.rs | 2 +- src/librustc/middle/trans/common.rs | 5 +- src/librustc/middle/trans/value.rs | 6 +- src/librustc/middle/typeck/astconv.rs | 15 +++-- src/librustc/middle/typeck/infer/combine.rs | 62 ++++++++++---------- src/librustc/middle/typeck/infer/glb.rs | 2 +- src/librustc/middle/typeck/infer/lattice.rs | 2 +- src/librustc/middle/typeck/infer/lub.rs | 4 +- src/librustc/middle/typeck/infer/mod.rs | 4 +- src/librustc/middle/typeck/infer/sub.rs | 2 +- src/librustc/middle/typeck/rscope.rs | 6 +- src/librustdoc/config.rs | 14 ++--- src/librustpkg/version.rs | 4 +- src/libstd/io.rs | 6 +- src/libstd/iter.rs | 19 ++++-- src/libstd/option.rs | 42 ++----------- src/libstd/result.rs | 65 +++++++++++++++++---- src/libstd/rt/io/net/ip.rs | 2 +- src/libsyntax/attr.rs | 4 +- src/libsyntax/ext/expand.rs | 17 ++++-- 25 files changed, 202 insertions(+), 161 deletions(-) diff --git a/src/libextra/num/rational.rs b/src/libextra/num/rational.rs index 41e9a488bf8a..1991d9f1b5bb 100644 --- a/src/libextra/num/rational.rs +++ b/src/libextra/num/rational.rs @@ -273,9 +273,9 @@ impl return None } let a_option: Option = FromStr::from_str(split[0]); - do a_option.chain |a| { + do a_option.and_then |a| { let b_option: Option = FromStr::from_str(split[1]); - do b_option.chain |b| { + do b_option.and_then |b| { Some(Ratio::new(a.clone(), b.clone())) } } @@ -291,10 +291,10 @@ impl } else { let a_option: Option = FromStrRadix::from_str_radix(split[0], radix); - do a_option.chain |a| { + do a_option.and_then |a| { let b_option: Option = FromStrRadix::from_str_radix(split[1], radix); - do b_option.chain |b| { + do b_option.and_then |b| { Some(Ratio::new(a.clone(), b.clone())) } } diff --git a/src/libextra/time.rs b/src/libextra/time.rs index 7515326a0dbb..d51d1c217857 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -442,21 +442,21 @@ fn do_strptime(s: &str, format: &str) -> Result { }, 'c' => { parse_type(s, pos, 'a', &mut *tm) - .chain(|pos| parse_char(s, pos, ' ')) - .chain(|pos| parse_type(s, pos, 'b', &mut *tm)) - .chain(|pos| parse_char(s, pos, ' ')) - .chain(|pos| parse_type(s, pos, 'e', &mut *tm)) - .chain(|pos| parse_char(s, pos, ' ')) - .chain(|pos| parse_type(s, pos, 'T', &mut *tm)) - .chain(|pos| parse_char(s, pos, ' ')) - .chain(|pos| parse_type(s, pos, 'Y', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ' ')) + .and_then(|pos| parse_type(s, pos, 'b', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ' ')) + .and_then(|pos| parse_type(s, pos, 'e', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ' ')) + .and_then(|pos| parse_type(s, pos, 'T', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ' ')) + .and_then(|pos| parse_type(s, pos, 'Y', &mut *tm)) } 'D' | 'x' => { parse_type(s, pos, 'm', &mut *tm) - .chain(|pos| parse_char(s, pos, '/')) - .chain(|pos| parse_type(s, pos, 'd', &mut *tm)) - .chain(|pos| parse_char(s, pos, '/')) - .chain(|pos| parse_type(s, pos, 'y', &mut *tm)) + .and_then(|pos| parse_char(s, pos, '/')) + .and_then(|pos| parse_type(s, pos, 'd', &mut *tm)) + .and_then(|pos| parse_char(s, pos, '/')) + .and_then(|pos| parse_type(s, pos, 'y', &mut *tm)) } 'd' => match match_digits_in_range(s, pos, 2u, false, 1_i32, 31_i32) { @@ -475,10 +475,10 @@ fn do_strptime(s: &str, format: &str) -> Result { } 'F' => { parse_type(s, pos, 'Y', &mut *tm) - .chain(|pos| parse_char(s, pos, '-')) - .chain(|pos| parse_type(s, pos, 'm', &mut *tm)) - .chain(|pos| parse_char(s, pos, '-')) - .chain(|pos| parse_type(s, pos, 'd', &mut *tm)) + .and_then(|pos| parse_char(s, pos, '-')) + .and_then(|pos| parse_type(s, pos, 'm', &mut *tm)) + .and_then(|pos| parse_char(s, pos, '-')) + .and_then(|pos| parse_type(s, pos, 'd', &mut *tm)) } 'H' => { match match_digits_in_range(s, pos, 2u, false, 0_i32, 23_i32) { @@ -553,17 +553,17 @@ fn do_strptime(s: &str, format: &str) -> Result { }, 'R' => { parse_type(s, pos, 'H', &mut *tm) - .chain(|pos| parse_char(s, pos, ':')) - .chain(|pos| parse_type(s, pos, 'M', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ':')) + .and_then(|pos| parse_type(s, pos, 'M', &mut *tm)) } 'r' => { parse_type(s, pos, 'I', &mut *tm) - .chain(|pos| parse_char(s, pos, ':')) - .chain(|pos| parse_type(s, pos, 'M', &mut *tm)) - .chain(|pos| parse_char(s, pos, ':')) - .chain(|pos| parse_type(s, pos, 'S', &mut *tm)) - .chain(|pos| parse_char(s, pos, ' ')) - .chain(|pos| parse_type(s, pos, 'p', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ':')) + .and_then(|pos| parse_type(s, pos, 'M', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ':')) + .and_then(|pos| parse_type(s, pos, 'S', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ' ')) + .and_then(|pos| parse_type(s, pos, 'p', &mut *tm)) } 'S' => { match match_digits_in_range(s, pos, 2u, false, 0_i32, 60_i32) { @@ -578,10 +578,10 @@ fn do_strptime(s: &str, format: &str) -> Result { //'s' {} 'T' | 'X' => { parse_type(s, pos, 'H', &mut *tm) - .chain(|pos| parse_char(s, pos, ':')) - .chain(|pos| parse_type(s, pos, 'M', &mut *tm)) - .chain(|pos| parse_char(s, pos, ':')) - .chain(|pos| parse_type(s, pos, 'S', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ':')) + .and_then(|pos| parse_type(s, pos, 'M', &mut *tm)) + .and_then(|pos| parse_char(s, pos, ':')) + .and_then(|pos| parse_type(s, pos, 'S', &mut *tm)) } 't' => parse_char(s, pos, '\t'), 'u' => { @@ -596,10 +596,10 @@ fn do_strptime(s: &str, format: &str) -> Result { } 'v' => { parse_type(s, pos, 'e', &mut *tm) - .chain(|pos| parse_char(s, pos, '-')) - .chain(|pos| parse_type(s, pos, 'b', &mut *tm)) - .chain(|pos| parse_char(s, pos, '-')) - .chain(|pos| parse_type(s, pos, 'Y', &mut *tm)) + .and_then(|pos| parse_char(s, pos, '-')) + .and_then(|pos| parse_type(s, pos, 'b', &mut *tm)) + .and_then(|pos| parse_char(s, pos, '-')) + .and_then(|pos| parse_type(s, pos, 'Y', &mut *tm)) } //'W' {} 'w' => { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 1841e25ee95e..5078d0ded18d 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -961,7 +961,7 @@ pub fn build_output_filenames(input: &input, if !linkage_metas.is_empty() { // But if a linkage meta is present, that overrides let maybe_name = linkage_metas.iter().find(|m| "name" == m.name()); - match maybe_name.chain(|m| m.value_str()) { + match maybe_name.and_then(|m| m.value_str()) { Some(s) => stem = s, _ => () } diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index 2a5c3ae0f4f0..2c0068729a72 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -58,7 +58,7 @@ fn filter_view_item<'r>(cx: @Context, view_item: &'r ast::view_item)-> Option<&' fn fold_mod(cx: @Context, m: &ast::_mod, fld: @fold::ast_fold) -> ast::_mod { let filtered_items = do m.items.iter().filter_map |a| { - filter_item(cx, *a).chain(|x| fld.fold_item(x)) + filter_item(cx, *a).and_then(|x| fld.fold_item(x)) }.collect(); let filtered_view_items = do m.view_items.iter().filter_map |a| { do filter_view_item(cx, a).map_move |x| { @@ -139,7 +139,7 @@ fn fold_block( fld: @fold::ast_fold ) -> ast::Block { let resulting_stmts = do b.stmts.iter().filter_map |a| { - filter_stmt(cx, *a).chain(|stmt| fld.fold_stmt(stmt)) + filter_stmt(cx, *a).and_then(|stmt| fld.fold_stmt(stmt)) }.collect(); let filtered_view_items = do b.view_items.iter().filter_map |a| { filter_view_item(cx, a).map(|x| fld.fold_view_item(*x)) diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index c463bd9bc033..3b563e47426a 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -184,7 +184,7 @@ fn visit_item(e: &Env, i: @ast::item) { ast::named => { let link_name = i.attrs.iter() .find(|at| "link_name" == at.name()) - .chain(|at| at.value_str()); + .and_then(|at| at.value_str()); let foreign_name = match link_name { Some(nn) => { diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 87108530c757..c94151095a44 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -210,7 +210,7 @@ fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) -> bool { } fn variant_disr_val(d: ebml::Doc) -> Option { - do reader::maybe_get_doc(d, tag_disr_val).chain |val_doc| { + do reader::maybe_get_doc(d, tag_disr_val).and_then |val_doc| { do reader::with_doc_data(val_doc) |data| { u64::parse_bytes(data, 10u) } } } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 242b15fe5f0d..267ac8b2f4df 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -505,7 +505,10 @@ impl get_node_info for ast::Block { impl get_node_info for Option<@ast::Expr> { fn info(&self) -> Option { - self.chain_ref(|s| s.info()) + match *self { + Some(ref s) => s.info(), + None => None, + } } } diff --git a/src/librustc/middle/trans/value.rs b/src/librustc/middle/trans/value.rs index 08b2db6eff9b..a33f2bd3a557 100644 --- a/src/librustc/middle/trans/value.rs +++ b/src/librustc/middle/trans/value.rs @@ -50,9 +50,9 @@ impl Value { /// must be the only user of this value, and there must not be any conditional /// branches between the store and the given block. pub fn get_dominating_store(self, bcx: @mut Block) -> Option { - match self.get_single_user().chain(|user| user.as_store_inst()) { + match self.get_single_user().and_then(|user| user.as_store_inst()) { Some(store) => { - do store.get_parent().chain |store_bb| { + do store.get_parent().and_then |store_bb| { let mut bb = BasicBlock(bcx.llbb); let mut ret = Some(store); while *bb != *store_bb { @@ -150,7 +150,7 @@ impl Iterator for UserIterator { fn next(&mut self) -> Option { let current = self.next; - self.next = do current.chain |u| { u.get_next_use() }; + self.next = do current.and_then |u| { u.get_next_use() }; do current.map |u| { u.get_user() } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index c5f85d26e446..f942638a8adf 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -745,10 +745,17 @@ pub fn ty_of_closure( RegionParamNames(bound_lifetime_names.clone())); let input_tys = do decl.inputs.iter().enumerate().map |(i, a)| { - let expected_arg_ty = do expected_sig.chain_ref |e| { - // no guarantee that the correct number of expected args - // were supplied - if i < e.inputs.len() {Some(e.inputs[i])} else {None} + let expected_arg_ty = match expected_sig { + Some(ref e) => { + // no guarantee that the correct number of expected args + // were supplied + if i < e.inputs.len() { + Some(e.inputs[i]) + } else { + None + } + } + None => None, }; ty_of_arg(this, &rb, a, expected_arg_ty) }.collect(); diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 9fc29250ed05..cdfb8732a38a 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -15,7 +15,7 @@ // the trait `Combine` and contains methods for combining two // instances of various things and yielding a new instance. These // combiner methods always yield a `result`---failure is propagated -// upward using `chain()` methods. There is a lot of common code for +// upward using `and_then()` methods. There is a lot of common code for // these operations, implemented as default methods on the `Combine` // trait. // @@ -108,7 +108,7 @@ pub trait Combine { (Some(a), Some(b)) => { // FIXME(#5781) this should be eq_tys // eq_tys(self, a, b).then(|| Ok(Some(a)) ) - self.contratys(a, b).chain(|t| Ok(Some(t))) + self.contratys(a, b).and_then(|t| Ok(Some(t))) } (None, Some(_)) | (Some(_), None) => { @@ -162,13 +162,13 @@ pub trait Combine { } ty::rv_covariant => { - do this.regions(a_r, b_r).chain |r| { + do this.regions(a_r, b_r).and_then |r| { Ok(ty::NonerasedRegions(opt_vec::with(r))) } } ty::rv_contravariant => { - do this.contraregions(a_r, b_r).chain |r| { + do this.contraregions(a_r, b_r).and_then |r| { Ok(ty::NonerasedRegions(opt_vec::with(r))) } } @@ -179,12 +179,12 @@ pub trait Combine { } } - do self.tps(as_.tps, bs.tps).chain |tps| { - do self.self_tys(as_.self_ty, bs.self_ty).chain |self_ty| { + do self.tps(as_.tps, bs.tps).and_then |tps| { + do self.self_tys(as_.self_ty, bs.self_ty).and_then |self_ty| { do relate_region_params(self, generics, &as_.regions, - &bs.regions).chain |regions| { + &bs.regions).and_then |regions| { Ok(substs { regions: regions, self_ty: self_ty, @@ -227,8 +227,8 @@ pub trait Combine { fn flds(&self, a: ty::field, b: ty::field) -> cres { if a.ident == b.ident { self.mts(&a.mt, &b.mt) - .chain(|mt| Ok(ty::field {ident: a.ident, mt: mt}) ) - .chain_err(|e| Err(ty::terr_in_field(@e, a.ident)) ) + .and_then(|mt| Ok(ty::field {ident: a.ident, mt: mt}) ) + .or_else(|e| Err(ty::terr_in_field(@e, a.ident)) ) } else { Err(ty::terr_record_fields( expected_found(self, @@ -238,7 +238,7 @@ pub trait Combine { } fn args(&self, a: ty::t, b: ty::t) -> cres { - do self.contratys(a, b).chain |t| { + do self.contratys(a, b).and_then |t| { Ok(t) } } @@ -274,7 +274,7 @@ pub trait Combine { match (a, b) { (ty::vstore_slice(a_r), ty::vstore_slice(b_r)) => { - do self.contraregions(a_r, b_r).chain |r| { + do self.contraregions(a_r, b_r).and_then |r| { Ok(ty::vstore_slice(r)) } } @@ -299,7 +299,7 @@ pub trait Combine { match (a, b) { (ty::RegionTraitStore(a_r), ty::RegionTraitStore(b_r)) => { - do self.contraregions(a_r, b_r).chain |r| { + do self.contraregions(a_r, b_r).and_then |r| { Ok(ty::RegionTraitStore(r)) } } @@ -357,7 +357,7 @@ pub fn expected_found( pub fn eq_tys(this: &C, a: ty::t, b: ty::t) -> ures { let suber = this.sub(); do this.infcx().try { - do suber.tys(a, b).chain |_ok| { + do suber.tys(a, b).and_then |_ok| { suber.contratys(a, b) }.to_ures() } @@ -371,10 +371,10 @@ pub fn eq_regions(this: &C, a: ty::Region, b: ty::Region) let sub = this.sub(); do indent { this.infcx().try(|| { - do sub.regions(a, b).chain |_r| { + do sub.regions(a, b).and_then |_r| { sub.contraregions(a, b) } - }).chain_err(|e| { + }).or_else(|e| { // substitute a better error, but use the regions // found in the original error match e { @@ -427,8 +427,8 @@ pub fn super_fn_sigs( } do argvecs(this, a.inputs, b.inputs) - .chain |inputs| { - do this.tys(a.output, b.output).chain |output| { + .and_then |inputs| { + do this.tys(a.output, b.output).and_then |output| { Ok(FnSig {bound_lifetime_names: opt_vec::Empty, // FIXME(#4846) inputs: inputs.clone(), output: output}) @@ -508,7 +508,7 @@ pub fn super_tys( &ty::ty_enum(b_id, ref b_substs)) if a_id == b_id => { let type_def = ty::lookup_item_type(tcx, a_id); - do this.substs(&type_def.generics, a_substs, b_substs).chain |substs| { + do this.substs(&type_def.generics, a_substs, b_substs).and_then |substs| { Ok(ty::mk_enum(tcx, a_id, substs)) } } @@ -517,9 +517,9 @@ pub fn super_tys( &ty::ty_trait(b_id, ref b_substs, b_store, b_mutbl, b_bounds)) if a_id == b_id && a_mutbl == b_mutbl => { let trait_def = ty::lookup_trait_def(tcx, a_id); - do this.substs(&trait_def.generics, a_substs, b_substs).chain |substs| { - do this.trait_stores(ty::terr_trait, a_store, b_store).chain |s| { - do this.bounds(a_bounds, b_bounds).chain |bounds| { + do this.substs(&trait_def.generics, a_substs, b_substs).and_then |substs| { + do this.trait_stores(ty::terr_trait, a_store, b_store).and_then |s| { + do this.bounds(a_bounds, b_bounds).and_then |bounds| { Ok(ty::mk_trait(tcx, a_id, substs.clone(), @@ -534,25 +534,25 @@ pub fn super_tys( (&ty::ty_struct(a_id, ref a_substs), &ty::ty_struct(b_id, ref b_substs)) if a_id == b_id => { let type_def = ty::lookup_item_type(tcx, a_id); - do this.substs(&type_def.generics, a_substs, b_substs).chain |substs| { + do this.substs(&type_def.generics, a_substs, b_substs).and_then |substs| { Ok(ty::mk_struct(tcx, a_id, substs)) } } (&ty::ty_box(ref a_mt), &ty::ty_box(ref b_mt)) => { - do this.mts(a_mt, b_mt).chain |mt| { + do this.mts(a_mt, b_mt).and_then |mt| { Ok(ty::mk_box(tcx, mt)) } } (&ty::ty_uniq(ref a_mt), &ty::ty_uniq(ref b_mt)) => { - do this.mts(a_mt, b_mt).chain |mt| { + do this.mts(a_mt, b_mt).and_then |mt| { Ok(ty::mk_uniq(tcx, mt)) } } (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => { - do this.mts(a_mt, b_mt).chain |mt| { + do this.mts(a_mt, b_mt).and_then |mt| { Ok(ty::mk_ptr(tcx, mt)) } } @@ -564,15 +564,15 @@ pub fn super_tys( } (&ty::ty_evec(ref a_mt, vs_a), &ty::ty_evec(ref b_mt, vs_b)) => { - do this.mts(a_mt, b_mt).chain |mt| { - do this.vstores(ty::terr_vec, vs_a, vs_b).chain |vs| { + do this.mts(a_mt, b_mt).and_then |mt| { + do this.vstores(ty::terr_vec, vs_a, vs_b).and_then |vs| { Ok(ty::mk_evec(tcx, mt, vs)) } } } (&ty::ty_estr(vs_a), &ty::ty_estr(vs_b)) => { - do this.vstores(ty::terr_str, vs_a, vs_b).chain |vs| { + do this.vstores(ty::terr_str, vs_a, vs_b).and_then |vs| { Ok(ty::mk_estr(tcx,vs)) } } @@ -581,7 +581,7 @@ pub fn super_tys( if as_.len() == bs.len() { result::collect(as_.iter().zip(bs.iter()) .map(|(a, b)| this.tys(*a, *b))) - .chain(|ts| Ok(ty::mk_tup(tcx, ts)) ) + .and_then(|ts| Ok(ty::mk_tup(tcx, ts)) ) } else { Err(ty::terr_tuple_size( expected_found(this, as_.len(), bs.len()))) @@ -589,13 +589,13 @@ pub fn super_tys( } (&ty::ty_bare_fn(ref a_fty), &ty::ty_bare_fn(ref b_fty)) => { - do this.bare_fn_tys(a_fty, b_fty).chain |fty| { + do this.bare_fn_tys(a_fty, b_fty).and_then |fty| { Ok(ty::mk_bare_fn(tcx, fty)) } } (&ty::ty_closure(ref a_fty), &ty::ty_closure(ref b_fty)) => { - do this.closure_tys(a_fty, b_fty).chain |fty| { + do this.closure_tys(a_fty, b_fty).and_then |fty| { Ok(ty::mk_closure(tcx, fty)) } } diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index 1939987d7f07..af62da5fde03 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -61,7 +61,7 @@ impl Combine for Glb { // If one side or both is immutable, we can use the GLB of // both sides but mutbl must be `MutImmutable`. (MutImmutable, MutImmutable) => { - self.tys(a.ty, b.ty).chain(|t| { + self.tys(a.ty, b.ty).and_then(|t| { Ok(ty::mt {ty: t, mutbl: MutImmutable}) }) } diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index 0ed30bb61b9f..4cbdf9fa1fb8 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -232,7 +232,7 @@ impl CombineFieldsLatticeMethods for CombineFields { (&Some(_), &None) => Ok((*a).clone()), (&None, &Some(_)) => Ok((*b).clone()), (&Some(ref v_a), &Some(ref v_b)) => { - do lattice_op(self, v_a, v_b).chain |v| { + do lattice_op(self, v_a, v_b).and_then |v| { Ok(Some(v)) } } diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index db5873f09fe2..260bc93611e9 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -62,7 +62,7 @@ impl Combine for Lub { let m = a.mutbl; match m { MutImmutable => { - self.tys(a.ty, b.ty).chain(|t| Ok(ty::mt {ty: t, mutbl: m}) ) + self.tys(a.ty, b.ty).and_then(|t| Ok(ty::mt {ty: t, mutbl: m}) ) } MutMutable => { @@ -70,7 +70,7 @@ impl Combine for Lub { eq_tys(self, a.ty, b.ty).then(|| { Ok(ty::mt {ty: a.ty, mutbl: m}) }) - }).chain_err(|e| Err(e)) + }).or_else(|e| Err(e)) } } } diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index a2d2cd92e135..e73a36de143c 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -451,7 +451,7 @@ trait then { impl then for ures { fn then(&self, f: &fn() -> Result) -> Result { - self.chain(|_i| f()) + self.and_then(|_i| f()) } } @@ -474,7 +474,7 @@ trait CresCompare { impl CresCompare for cres { fn compare(&self, t: T, f: &fn() -> ty::type_err) -> cres { - do (*self).clone().chain |s| { + do (*self).clone().and_then |s| { if s == t { (*self).clone() } else { diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 36c5f8a50d28..57ebb2185d16 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -79,7 +79,7 @@ impl Combine for Sub { } MutImmutable => { // Otherwise we can be covariant: - self.tys(a.ty, b.ty).chain(|_t| Ok(*a) ) + self.tys(a.ty, b.ty).and_then(|_t| Ok(*a) ) } } } diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index d3dc3d1fb1c9..1967122745da 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -202,7 +202,7 @@ impl RegionScope for MethodRscope { if !self.region_param_names.has_ident(id) { return RegionParamNames::undeclared_name(None); } - do EmptyRscope.named_region(span, id).chain_err |_e| { + do EmptyRscope.named_region(span, id).or_else |_e| { result::Err(RegionError { msg: ~"lifetime is not in scope", replacement: ty::re_bound(ty::br_self) @@ -251,7 +251,7 @@ impl RegionScope for TypeRscope { } fn named_region(&self, span: Span, id: ast::Ident) -> Result { - do EmptyRscope.named_region(span, id).chain_err |_e| { + do EmptyRscope.named_region(span, id).or_else |_e| { result::Err(RegionError { msg: ~"only 'self is allowed as part of a type declaration", replacement: self.replacement() @@ -310,7 +310,7 @@ impl RegionScope for BindingRscope { span: Span, id: ast::Ident) -> Result { - do self.base.named_region(span, id).chain_err |_e| { + do self.base.named_region(span, id).or_else |_e| { let result = ty::re_bound(ty::br_named(id)); if self.region_param_names.has_ident(id) { result::Ok(result) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index c8dd38394c96..ff6401456b6b 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -138,7 +138,7 @@ fn config_from_opts( let config = default_config(input_crate); let result = result::Ok(config); - let result = do result.chain |config| { + let result = do result.and_then |config| { let output_dir = getopts::opt_maybe_str(matches, opt_output_dir()); let output_dir = output_dir.map_move(|s| Path(s)); result::Ok(Config { @@ -146,10 +146,10 @@ fn config_from_opts( .. config }) }; - let result = do result.chain |config| { + let result = do result.and_then |config| { let output_format = getopts::opt_maybe_str(matches, opt_output_format()); do output_format.map_move_default(result::Ok(config.clone())) |output_format| { - do parse_output_format(output_format).chain |output_format| { + do parse_output_format(output_format).and_then |output_format| { result::Ok(Config { output_format: output_format, .. config.clone() @@ -157,11 +157,11 @@ fn config_from_opts( } } }; - let result = do result.chain |config| { + let result = do result.and_then |config| { let output_style = getopts::opt_maybe_str(matches, opt_output_style()); do output_style.map_move_default(result::Ok(config.clone())) |output_style| { - do parse_output_style(output_style).chain |output_style| { + do parse_output_style(output_style).and_then |output_style| { result::Ok(Config { output_style: output_style, .. config.clone() @@ -170,11 +170,11 @@ fn config_from_opts( } }; let process_output = Cell::new(process_output); - let result = do result.chain |config| { + let result = do result.and_then |config| { let pandoc_cmd = getopts::opt_maybe_str(matches, opt_pandoc_cmd()); let pandoc_cmd = maybe_find_pandoc( &config, pandoc_cmd, process_output.take()); - do pandoc_cmd.chain |pandoc_cmd| { + do pandoc_cmd.and_then |pandoc_cmd| { result::Ok(Config { pandoc_cmd: pandoc_cmd, .. config.clone() diff --git a/src/librustpkg/version.rs b/src/librustpkg/version.rs index c2d87ddeb82b..6eb4cc56a2bd 100644 --- a/src/librustpkg/version.rs +++ b/src/librustpkg/version.rs @@ -118,7 +118,7 @@ pub fn try_getting_local_version(local_path: &Path) -> Option { if !l.is_whitespace() { output = Some(l); } - match output.chain(try_parsing_version) { + match output.and_then(try_parsing_version) { Some(v) => return Some(v), None => () } @@ -158,7 +158,7 @@ pub fn try_getting_version(remote_path: &Path) -> Option { } } - output.chain(try_parsing_version) + output.and_then(try_parsing_version) } else { None diff --git a/src/libstd/io.rs b/src/libstd/io.rs index e9b704c2686f..2ca36de4f49c 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -1618,7 +1618,7 @@ impl WriterUtil for T { } pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> { - mk_file_writer(path, flags).chain(|w| Ok(w)) + mk_file_writer(path, flags).and_then(|w| Ok(w)) } @@ -1779,7 +1779,7 @@ pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) -> } pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> { - do read_whole_file(file).chain |bytes| { + do read_whole_file(file).and_then |bytes| { if str::is_utf8(bytes) { Ok(str::from_utf8(bytes)) } else { @@ -1791,7 +1791,7 @@ pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> { // FIXME (#2004): implement this in a low-level way. Going through the // abstractions is pointless. pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> { - do file_reader(file).chain |rdr| { + do file_reader(file).and_then |rdr| { Ok(rdr.read_whole_stream()) } } diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 5ca827350d01..f36fb2d98bdf 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -1474,7 +1474,7 @@ pub struct Scan<'self, A, B, T, St> { impl<'self, A, B, T: Iterator, St> Iterator for Scan<'self, A, B, T, St> { #[inline] fn next(&mut self) -> Option { - self.iter.next().chain(|a| (self.f)(&mut self.state, a)) + self.iter.next().and_then(|a| (self.f)(&mut self.state, a)) } #[inline] @@ -1494,8 +1494,7 @@ pub struct FlatMap<'self, A, T, U> { priv backiter: Option, } -impl<'self, A, T: Iterator, B, U: Iterator> Iterator for - FlatMap<'self, A, T, U> { +impl<'self, A, T: Iterator, B, U: Iterator> Iterator for FlatMap<'self, A, T, U> { #[inline] fn next(&mut self) -> Option { loop { @@ -1505,7 +1504,12 @@ impl<'self, A, T: Iterator, B, U: Iterator> Iterator for } } match self.iter.next().map_move(|x| (self.f)(x)) { - None => return self.backiter.chain_mut_ref(|it| it.next()), + None => { + return match self.backiter { + Some(ref mut it) => it.next(), + None => None, + }; + } next => self.frontiter = next, } } @@ -1537,7 +1541,12 @@ impl<'self, } } match self.iter.next_back().map_move(|x| (self.f)(x)) { - None => return self.frontiter.chain_mut_ref(|it| it.next_back()), + None => { + return match self.frontiter { + Some(ref mut it) => it.next_back(), + None => None, + }; + } next => self.backiter = next, } } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index cd9e39807160..9b5b28d5cebb 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -141,9 +141,9 @@ impl Option { /// Returns `None` if the option is `None`, otherwise calls and returns the /// value of `f`. #[inline] - pub fn and_then(self, f: &fn() -> Option) -> Option { + pub fn and_then(self, f: &fn(T) -> Option) -> Option { match self { - Some(_) => f(), + Some(x) => f(x), None => None, } } @@ -167,36 +167,6 @@ impl Option { } } - /// Update an optional value by optionally running its content through a - /// function that returns an option. - #[inline] - pub fn chain(self, f: &fn(T) -> Option) -> Option { - match self { - Some(t) => f(t), - None => None - } - } - - /// Update an optional value by optionally running its content by reference - /// through a function that returns an option. - #[inline] - pub fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option) -> Option { - match *self { - Some(ref x) => f(x), - None => None - } - } - - /// Update an optional value by optionally running its content by mut reference - /// through a function that returns an option. - #[inline] - pub fn chain_mut_ref<'a, U>(&'a mut self, f: &fn(x: &'a mut T) -> Option) -> Option { - match *self { - Some(ref mut x) => f(x), - None => None - } - } - /// Filters an optional value using given function. #[inline(always)] pub fn filtered(self, f: &fn(t: &T) -> bool) -> Option { @@ -637,12 +607,12 @@ mod tests { #[test] fn test_and_then() { let x: Option = Some(1); - assert_eq!(x.and_then(|| Some(2)), Some(2)); - assert_eq!(x.and_then(|| None), None); + assert_eq!(x.and_then(|x| Some(x + 1)), Some(2)); + assert_eq!(x.and_then(|_| None::), None); let x: Option = None; - assert_eq!(x.and_then(|| Some(2)), None); - assert_eq!(x.and_then(|| None), None); + assert_eq!(x.and_then(|x| Some(x + 1)), None); + assert_eq!(x.and_then(|_| None::), None); } #[test] diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 20b65f1576d7..3811f34cec43 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -171,10 +171,22 @@ impl Result { } } + /// Call a method based on a previous result + /// + /// If `self` is `Ok`, then `res` it is returned. If `self` is `Err`, + /// then `self` is returned. + #[inline] + pub fn and(self, res: Result) -> Result { + match self { + Ok(_) => res, + Err(_) => self, + } + } + /// Call a method based on a previous result /// /// If `self` is `Ok` then the value is extracted and passed to `op` - /// whereupon `op`s result is returned. if `self` is `Err` then it is + /// whereupon `op`s result is returned. If `self` is `Err` then it is /// immediately returned. This function can be used to compose the results /// of two functions. /// @@ -184,13 +196,25 @@ impl Result { /// Ok(parse_bytes(buf)) /// }; #[inline] - pub fn chain(self, op: &fn(T) -> Result) -> Result { + pub fn and_then(self, op: &fn(T) -> Result) -> Result { match self { Ok(t) => op(t), Err(e) => Err(e), } } + /// Call a method based on a previous result + /// + /// If `self` is `Ok`, then `self` is returned. If `self` is `Err` + /// then `res` is returned. + #[inline] + pub fn or(self, res: Result) -> Result { + match self { + Ok(_) => self, + Err(_) => res, + } + } + /// Call a function based on a previous result /// /// If `self` is `Err` then the value is extracted and passed to `op` @@ -198,7 +222,7 @@ impl Result { /// immediately returned. This function can be used to pass through a /// successful result while handling an error. #[inline] - pub fn chain_err(self, op: &fn(E) -> Result) -> Result { + pub fn or_else(self, op: &fn(E) -> Result) -> Result { match self { Ok(t) => Ok(t), Err(e) => op(e), @@ -430,21 +454,42 @@ mod tests { use vec::ImmutableVector; pub fn op1() -> Result { Ok(666) } + pub fn op2() -> Result { Err(~"sadface") } + + #[test] + pub fn test_and() { + assert_eq!(op1().and(Ok(667)).unwrap(), 667); + assert_eq!(op1().and(Err(~"bad")).unwrap_err(), ~"bad"); - pub fn op2(i: int) -> Result { - Ok(i as uint + 1u) + assert_eq!(op2().and(Ok(667)).unwrap_err(), ~"sadface"); + assert_eq!(op2().and(Err(~"bad")).unwrap_err(), ~"sadface"); } - pub fn op3() -> Result { Err(~"sadface") } + #[test] + pub fn test_and_then() { + assert_eq!(op1().and_then(|i| Ok::(i + 1)).unwrap(), 667); + assert_eq!(op1().and_then(|_| Err::(~"bad")).unwrap_err(), ~"bad"); + + assert_eq!(op2().and_then(|i| Ok::(i + 1)).unwrap_err(), ~"sadface"); + assert_eq!(op2().and_then(|_| Err::(~"bad")).unwrap_err(), ~"sadface"); + } #[test] - pub fn chain_success() { - assert_eq!(op1().chain(op2).unwrap(), 667u); + pub fn test_or() { + assert_eq!(op1().or(Ok(667)).unwrap(), 666); + assert_eq!(op1().or(Err(~"bad")).unwrap(), 666); + + assert_eq!(op2().or(Ok(667)).unwrap(), 667); + assert_eq!(op2().or(Err(~"bad")).unwrap_err(), ~"bad"); } #[test] - pub fn chain_failure() { - assert_eq!(op3().chain( op2).unwrap_err(), ~"sadface"); + pub fn test_or_else() { + assert_eq!(op1().or_else(|_| Ok::(667)).unwrap(), 666); + assert_eq!(op1().or_else(|e| Err::(e + "!")).unwrap(), 666); + + assert_eq!(op2().or_else(|_| Ok::(667)).unwrap(), 667); + assert_eq!(op2().or_else(|e| Err::(e + "!")).unwrap_err(), ~"sadface!"); } #[test] diff --git a/src/libstd/rt/io/net/ip.rs b/src/libstd/rt/io/net/ip.rs index 956dd08ac91f..041253455f01 100644 --- a/src/libstd/rt/io/net/ip.rs +++ b/src/libstd/rt/io/net/ip.rs @@ -177,7 +177,7 @@ impl<'self> Parser<'self> { } do self.read_atomically |p| { - p.read_char().chain(|c| parse_digit(c, radix)) + p.read_char().and_then(|c| parse_digit(c, radix)) } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index fd0887de7224..295485d6f6ef 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -187,12 +187,12 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option<@str> { attrs.iter() .find(|at| name == at.name()) - .chain(|at| at.value_str()) + .and_then(|at| at.value_str()) } pub fn last_meta_item_value_str_by_name(items: &[@MetaItem], name: &str) -> Option<@str> { - items.rev_iter().find(|mi| name == mi.name()).chain(|i| i.value_str()) + items.rev_iter().find(|mi| name == mi.name()).and_then(|i| i.value_str()) } /* Higher-level applications */ diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2cebae550fd5..4d62285cf6ee 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -331,11 +331,18 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, }; let maybe_it = match expanded { - MRItem(it) => mark_item(it,fm).chain(|i| {fld.fold_item(i)}), - MRExpr(_) => cx.span_fatal(pth.span, - fmt!("expr macro in item position: %s", extnamestr)), - MRAny(_, item_maker, _) => item_maker().chain(|i| {mark_item(i,fm)}) - .chain(|i| {fld.fold_item(i)}), + MRItem(it) => { + mark_item(it,fm) + .and_then(|i| fld.fold_item(i)) + } + MRExpr(_) => { + cx.span_fatal(pth.span, fmt!("expr macro in item position: %s", extnamestr)) + } + MRAny(_, item_maker, _) => { + item_maker() + .and_then(|i| mark_item(i,fm)) + .and_then(|i| fld.fold_item(i)) + } MRDef(ref mdef) => { // yikes... no idea how to apply the mark to this. I'm afraid // we're going to have to wait-and-see on this one. From ca47eebb44431c1ded5cc5c412d95210f3955ef4 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 21:49:25 -0700 Subject: [PATCH 14/21] std: Add a bunch of Default impls --- src/libextra/uuid.rs | 7 +++++++ src/libstd/bool.rs | 7 +++++++ src/libstd/char.rs | 10 ++++++++++ src/libstd/default.rs | 12 ++++++++++++ src/libstd/num/f32.rs | 6 ++++++ src/libstd/num/f64.rs | 6 ++++++ src/libstd/num/float.rs | 6 ++++++ src/libstd/num/int_macros.rs | 6 ++++++ src/libstd/num/uint_macros.rs | 6 ++++++ src/libstd/option.rs | 1 + src/libstd/tuple.rs | 9 +++++++++ src/libstd/unit.rs | 11 ++++++----- 12 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/libextra/uuid.rs b/src/libextra/uuid.rs index b2c0f24824fc..2641c1379e4f 100644 --- a/src/libextra/uuid.rs +++ b/src/libextra/uuid.rs @@ -417,6 +417,13 @@ impl Uuid { } } +impl Default for Uuid { + /// Returns the nil UUID, which is all zeroes + fn default() -> Uuid { + Uuid::new_nil() + } +} + impl Zero for Uuid { /// Returns the nil UUID, which is all zeroes fn zero() -> Uuid { diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs index 926e6e1f6b6e..4ef50094139a 100644 --- a/src/libstd/bool.rs +++ b/src/libstd/bool.rs @@ -24,6 +24,7 @@ Implementations of the following traits: * `Ord` * `TotalOrd` * `Eq` +* `Default` * `Zero` ## Various functions to compare `bool`s @@ -43,6 +44,7 @@ use to_str::ToStr; #[cfg(not(test))] use cmp::{Eq, Ord, TotalOrd, Ordering}; #[cfg(not(test))] use ops::Not; +#[cfg(not(test))] use default::Default; #[cfg(not(test))] use num::Zero; /** @@ -323,6 +325,11 @@ impl Eq for bool { fn eq(&self, other: &bool) -> bool { (*self) == (*other) } } +#[cfg(not(test))] +impl Default for bool { + fn default() -> bool { false } +} + #[cfg(not(test))] impl Zero for bool { fn zero() -> bool { false } diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 7f043b2ecaab..3a01e5908d9d 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -21,6 +21,7 @@ use str; #[cfg(test)] use str::OwnedStr; #[cfg(not(test))] use cmp::{Eq, Ord}; +#[cfg(not(test))] use default::Default; #[cfg(not(test))] use num::Zero; // UTF-8 ranges and tags for encoding characters @@ -434,9 +435,18 @@ impl Ord for char { fn lt(&self, other: &char) -> bool { *self < *other } } +#[cfg(not(test))] +impl Default for char { + #[inline] + fn default() -> char { '\x00' } +} + #[cfg(not(test))] impl Zero for char { + #[inline] fn zero() -> char { '\x00' } + + #[inline] fn is_zero(&self) -> bool { *self == '\x00' } } diff --git a/src/libstd/default.rs b/src/libstd/default.rs index fbc60ffd01b3..120cf3fa8013 100644 --- a/src/libstd/default.rs +++ b/src/libstd/default.rs @@ -15,3 +15,15 @@ pub trait Default { /// Return the "default value" for a type. fn default() -> Self; } + +impl Default for @mut T { + fn default() -> @mut T { @mut Default::default() } +} + +impl Default for @T { + fn default() -> @T { @Default::default() } +} + +impl Default for ~T { + fn default() -> ~T { ~Default::default() } +} diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 899d6236aaaa..0addcce3eb60 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -12,6 +12,7 @@ #[allow(missing_doc)]; #[allow(non_uppercase_statics)]; +use default::Default; use libc::c_int; use num::{Zero, One, strconv}; use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal}; @@ -237,6 +238,11 @@ impl Orderable for f32 { } } +impl Default for f32 { + #[inline] + fn default() -> f32 { 0.0 } +} + impl Zero for f32 { #[inline] fn zero() -> f32 { 0.0 } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 6ab8350a1154..b0675278238e 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -13,6 +13,7 @@ #[allow(missing_doc)]; #[allow(non_uppercase_statics)]; +use default::Default; use libc::c_int; use num::{Zero, One, strconv}; use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal}; @@ -260,6 +261,11 @@ impl Orderable for f64 { } } +impl Default for f64 { + #[inline] + fn default() -> f64 { 0.0 } +} + impl Zero for f64 { #[inline] fn zero() -> f64 { 0.0 } diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs index df26fadae165..3952f5478f7f 100644 --- a/src/libstd/num/float.rs +++ b/src/libstd/num/float.rs @@ -23,6 +23,7 @@ #[allow(missing_doc)]; #[allow(non_uppercase_statics)]; +use default::Default; use num::{Zero, One, strconv}; use num::FPCategory; use num; @@ -382,6 +383,11 @@ impl Orderable for float { } } +impl Default for float { + #[inline] + fn default() -> float { 0.0 } +} + impl Zero for float { #[inline] fn zero() -> float { 0.0 } diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 07cafb0a4f12..ae2a56b835dd 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -16,6 +16,7 @@ macro_rules! int_module (($T:ty, $bits:expr) => (mod generated { #[allow(non_uppercase_statics)]; +use default::Default; use num::{ToStrRadix, FromStrRadix}; use num::{CheckedDiv, Zero, One, strconv}; use prelude::*; @@ -167,6 +168,11 @@ impl Orderable for $T { } } +impl Default for $T { + #[inline] + fn default() -> $T { 0 } +} + impl Zero for $T { #[inline] fn zero() -> $T { 0 } diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index effeb60fc220..3deb7312b04f 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -16,6 +16,7 @@ macro_rules! uint_module (($T:ty, $T_SIGNED:ty, $bits:expr) => (mod generated { #[allow(non_uppercase_statics)]; +use default::Default; use num::BitCount; use num::{ToStrRadix, FromStrRadix}; use num::{CheckedDiv, Zero, One, strconv}; @@ -172,6 +173,11 @@ impl Orderable for $T { } } +impl Default for $T { + #[inline] + fn default() -> $T { 0 } +} + impl Zero for $T { #[inline] fn zero() -> $T { 0 } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 9b5b28d5cebb..dd5b71c6dd48 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -459,6 +459,7 @@ impl Option { } impl Default for Option { + #[inline] fn default() -> Option { None } } diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index 5d9ca6202e26..2591131f2152 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -89,6 +89,7 @@ macro_rules! tuple_impls { pub mod inner { use clone::Clone; #[cfg(not(test))] use cmp::*; + #[cfg(not(test))] use default::Default; #[cfg(not(test))] use num::Zero; $( @@ -172,6 +173,14 @@ macro_rules! tuple_impls { } } + #[cfg(not(test))] + impl<$($T:Default),+> Default for ($($T,)+) { + #[inline] + fn default() -> ($($T,)+) { + ($({ let x: $T = Default::default(); x},)+) + } + } + #[cfg(not(test))] impl<$($T:Zero),+> Zero for ($($T,)+) { #[inline] diff --git a/src/libstd/unit.rs b/src/libstd/unit.rs index 3af0322df56d..dfe4abe54e5b 100644 --- a/src/libstd/unit.rs +++ b/src/libstd/unit.rs @@ -45,6 +45,12 @@ impl TotalEq for () { fn equals(&self, _other: &()) -> bool { true } } +#[cfg(not(test))] +impl Default for () { + #[inline] + fn default() -> () { () } +} + #[cfg(not(test))] impl Zero for () { #[inline] @@ -52,8 +58,3 @@ impl Zero for () { #[inline] fn is_zero(&self) -> bool { true } } - -#[cfg(not(test))] -impl Default for () { - fn default() -> () { () } -} From a0e123eb6e2c0a971dd4e9e2c49e2ceed0d73672 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 21:51:13 -0700 Subject: [PATCH 15/21] syntax: add #[deriving(Default)] syntax extension --- src/libextra/glob.rs | 44 ++++++++++++++- src/libsyntax/ext/deriving/default.rs | 79 +++++++++++++++++++++++++++ src/libsyntax/ext/deriving/mod.rs | 2 + 3 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 src/libsyntax/ext/deriving/default.rs diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs index 984a09aed3e3..2811b939cc21 100644 --- a/src/libextra/glob.rs +++ b/src/libextra/glob.rs @@ -137,7 +137,17 @@ fn list_dir_sorted(path: &Path) -> ~[Path] { /** * A compiled Unix shell style pattern. */ -#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Zero)] +#[cfg(stage0)] +#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes)] +pub struct Pattern { + priv tokens: ~[PatternToken] +} + +/** + * A compiled Unix shell style pattern. + */ +#[cfg(not(stage0))] +#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Default)] pub struct Pattern { priv tokens: ~[PatternToken] } @@ -458,7 +468,37 @@ fn is_sep(c: char) -> bool { /** * Configuration options to modify the behaviour of `Pattern::matches_with(..)` */ -#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Zero)] +#[cfg(stage0)] +#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes)] +pub struct MatchOptions { + + /** + * Whether or not patterns should be matched in a case-sensitive manner. This + * currently only considers upper/lower case relationships between ASCII characters, + * but in future this might be extended to work with Unicode. + */ + case_sensitive: bool, + + /** + * If this is true then path-component separator characters (e.g. `/` on Posix) + * must be matched by a literal `/`, rather than by `*` or `?` or `[...]` + */ + require_literal_separator: bool, + + /** + * If this is true then paths that contain components that start with a `.` will + * not match unless the `.` appears literally in the pattern: `*`, `?` or `[...]` + * will not match. This is useful because such files are conventionally considered + * hidden on Unix systems and it might be desirable to skip them when listing files. + */ + require_literal_leading_dot: bool +} + +/** + * Configuration options to modify the behaviour of `Pattern::matches_with(..)` + */ +#[cfg(not(stage0))] +#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Default)] pub struct MatchOptions { /** diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs new file mode 100644 index 000000000000..0c7bbefc6901 --- /dev/null +++ b/src/libsyntax/ext/deriving/default.rs @@ -0,0 +1,79 @@ +// 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. + +use ast::{MetaItem, item, Expr}; +use codemap::Span; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; + +use std::vec; + +pub fn expand_deriving_default(cx: @ExtCtxt, + span: Span, + mitem: @MetaItem, + in_items: ~[@item]) + -> ~[@item] { + let trait_def = TraitDef { + path: Path::new(~["std", "default", "Default"]), + additional_bounds: ~[], + generics: LifetimeBounds::empty(), + methods: ~[ + MethodDef { + name: "default", + generics: LifetimeBounds::empty(), + explicit_self: None, + args: ~[], + ret_ty: Self, + const_nonmatching: false, + combine_substructure: default_substructure + }, + ] + }; + trait_def.expand(cx, span, mitem, in_items) +} + +fn default_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr { + let default_ident = ~[ + cx.ident_of("std"), + cx.ident_of("default"), + cx.ident_of("Default"), + cx.ident_of("default") + ]; + let default_call = || { + cx.expr_call_global(span, default_ident.clone(), ~[]) + }; + + return match *substr.fields { + StaticStruct(_, ref summary) => { + match *summary { + Left(count) => { + if count == 0 { + cx.expr_ident(span, substr.type_ident) + } else { + let exprs = vec::from_fn(count, |_| default_call()); + cx.expr_call_ident(span, substr.type_ident, exprs) + } + } + Right(ref fields) => { + let default_fields = do fields.map |ident| { + cx.field_imm(span, *ident, default_call()) + }; + cx.expr_struct_ident(span, substr.type_ident, default_fields) + } + } + } + StaticEnum(*) => { + cx.span_fatal(span, "`Default` cannot be derived for enums, \ + only structs") + } + _ => cx.bug("Non-static method in `deriving(Default)`") + }; +} diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 7fd44bfad01f..dfd4f79cd9e3 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -31,6 +31,7 @@ pub mod decodable; pub mod rand; pub mod to_str; pub mod zero; +pub mod default; #[path="cmp/eq.rs"] pub mod eq; @@ -97,6 +98,7 @@ pub fn expand_meta_deriving(cx: @ExtCtxt, "ToStr" => expand!(to_str::expand_deriving_to_str), "Zero" => expand!(zero::expand_deriving_zero), + "Default" => expand!(default::expand_deriving_default), ref tname => { cx.span_err(titem.span, fmt!("unknown \ From 43aba856b4a8d1b2068f1f5c5017934442d2aedd Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 22:16:22 -0700 Subject: [PATCH 16/21] std: Remove Zero impl from vec Vecs are not numeric types, so it doesn't make sense for them to implement Zero. --- src/libstd/vec.rs | 25 ++++--------------------- src/test/run-pass/deriving-zero.rs | 7 +++---- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index b91384f0ba50..47c3a0796144 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -107,7 +107,7 @@ use cmp; use default::Default; use iter::*; use libc::c_void; -use num::{Integer, Zero, CheckedAdd, Saturating}; +use num::{Integer, CheckedAdd, Saturating}; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; use ptr; @@ -2250,22 +2250,6 @@ impl Default for @[A] { fn default() -> @[A] { @[] } } -// This works because every lifetime is a sub-lifetime of 'static -impl<'self, A> Zero for &'self [A] { - fn zero() -> &'self [A] { &'self [] } - fn is_zero(&self) -> bool { self.is_empty() } -} - -impl Zero for ~[A] { - fn zero() -> ~[A] { ~[] } - fn is_zero(&self) -> bool { self.len() == 0 } -} - -impl Zero for @[A] { - fn zero() -> @[A] { @[] } - fn is_zero(&self) -> bool { self.len() == 0 } -} - macro_rules! iterator { /* FIXME: #4375 Cannot attach documentation/attributes to a macro generated struct. (struct $name:ident -> $ptr:ty, $elem:ty) => { @@ -3602,13 +3586,12 @@ mod tests { } #[test] - fn test_vec_zero() { - use num::Zero; + fn test_vec_default() { + use default::Default; macro_rules! t ( ($ty:ty) => {{ - let v: $ty = Zero::zero(); + let v: $ty = Default::default(); assert!(v.is_empty()); - assert!(v.is_zero()); }} ); diff --git a/src/test/run-pass/deriving-zero.rs b/src/test/run-pass/deriving-zero.rs index aba23e53282c..9d92e2400ef4 100644 --- a/src/test/run-pass/deriving-zero.rs +++ b/src/test/run-pass/deriving-zero.rs @@ -29,10 +29,9 @@ struct Lots { e: char, f: float, g: (f32, char), - h: ~[util::NonCopyable], - i: @mut (int, int), - j: bool, - k: (), + h: @mut (int, int), + i: bool, + j: (), } fn main() { From f107718a9b09daeedb5c0a3ea9b4ecb044afff44 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 11 Sep 2013 22:19:19 -0700 Subject: [PATCH 17/21] std: Remove Zero impl for Option Options are not numeric types, so it doesn't make sense for them to implement Zero. --- src/libstd/option.rs | 5 ----- src/test/run-pass/deriving-zero.rs | 1 - 2 files changed, 6 deletions(-) diff --git a/src/libstd/option.rs b/src/libstd/option.rs index dd5b71c6dd48..968330a18a85 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -483,11 +483,6 @@ impl Option { } } -impl Zero for Option { - fn zero() -> Option { None } - fn is_zero(&self) -> bool { self.is_none() } -} - /// An iterator that yields either one or zero elements #[deriving(Clone, DeepClone)] pub struct OptionIterator { diff --git a/src/test/run-pass/deriving-zero.rs b/src/test/run-pass/deriving-zero.rs index 9d92e2400ef4..fb4ffb2c3c15 100644 --- a/src/test/run-pass/deriving-zero.rs +++ b/src/test/run-pass/deriving-zero.rs @@ -24,7 +24,6 @@ struct E { a: int, b: int } #[deriving(Zero)] struct Lots { - c: Option, d: u8, e: char, f: float, From 7c08abb0cee1a1e679b654d2dd17f38317b58621 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 12 Sep 2013 06:39:45 -0700 Subject: [PATCH 18/21] Document the Zero trait --- doc/rust.md | 3 ++- doc/tutorial.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 730f78ea0820..8e1028b47273 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1717,7 +1717,8 @@ Supported traits for `deriving` are: * `Clone` and `DeepClone`, to perform (deep) copies. * `IterBytes`, to iterate over the bytes in a data type. * `Rand`, to create a random instance of a data type. -* `Zero`, to create an zero (or empty) instance of a data type. +* `Default`, to create an empty instance of a data type. +* `Zero`, to create an zero instance of a numeric data type. * `ToStr`, to convert to a string. For a type with this instance, `obj.to_str()` has similar output as `fmt!("%?", obj)`, but it differs in that each constituent field of the type must also implement `ToStr` and will have diff --git a/doc/tutorial.md b/doc/tutorial.md index 7614e8482377..637dbb10c235 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -2249,7 +2249,7 @@ enum ABC { A, B, C } The full list of derivable traits is `Eq`, `TotalEq`, `Ord`, `TotalOrd`, `Encodable` `Decodable`, `Clone`, `DeepClone`, -`IterBytes`, `Rand`, `Zero`, and `ToStr`. +`IterBytes`, `Rand`, `Default`, `Zero`, and `ToStr`. # Crates and the module system From 7f9c5aae9e9d94b88cb7507633f449534d32c109 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 12 Sep 2013 18:54:02 -0700 Subject: [PATCH 19/21] std: Restore Option::chain{,_mut}_ref as and_then{,_mut}_ref --- src/librustc/middle/trans/common.rs | 5 +---- src/librustc/middle/typeck/astconv.rs | 15 ++++---------- src/libstd/iter.rs | 14 ++------------ src/libstd/option.rs | 28 +++++++++++++++++++++++---- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 267ac8b2f4df..b75b06f42b64 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -505,10 +505,7 @@ impl get_node_info for ast::Block { impl get_node_info for Option<@ast::Expr> { fn info(&self) -> Option { - match *self { - Some(ref s) => s.info(), - None => None, - } + self.and_then_ref(|s| s.info()) } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index f942638a8adf..36405136e630 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -745,17 +745,10 @@ pub fn ty_of_closure( RegionParamNames(bound_lifetime_names.clone())); let input_tys = do decl.inputs.iter().enumerate().map |(i, a)| { - let expected_arg_ty = match expected_sig { - Some(ref e) => { - // no guarantee that the correct number of expected args - // were supplied - if i < e.inputs.len() { - Some(e.inputs[i]) - } else { - None - } - } - None => None, + let expected_arg_ty = do expected_sig.and_then_ref |e| { + // no guarantee that the correct number of expected args + // were supplied + if i < e.inputs.len() {Some(e.inputs[i])} else {None} }; ty_of_arg(this, &rb, a, expected_arg_ty) }.collect(); diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index f36fb2d98bdf..ec3c02a31f2f 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -1504,12 +1504,7 @@ impl<'self, A, T: Iterator, B, U: Iterator> Iterator for FlatMap<'self, } } match self.iter.next().map_move(|x| (self.f)(x)) { - None => { - return match self.backiter { - Some(ref mut it) => it.next(), - None => None, - }; - } + None => return self.backiter.and_then_mut_ref(|it| it.next()), next => self.frontiter = next, } } @@ -1541,12 +1536,7 @@ impl<'self, } } match self.iter.next_back().map_move(|x| (self.f)(x)) { - None => { - return match self.frontiter { - Some(ref mut it) => it.next_back(), - None => None, - }; - } + None => return self.frontiter.and_then_mut_ref(|it| it.next_back()), next => self.backiter = next, } } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 968330a18a85..ce725257dfff 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -138,8 +138,8 @@ impl Option { } } - /// Returns `None` if the option is `None`, otherwise calls and returns the - /// value of `f`. + /// Returns `None` if the option is `None`, otherwise calls `f` with the + /// wrapped value and returns the result. #[inline] pub fn and_then(self, f: &fn(T) -> Option) -> Option { match self { @@ -148,6 +148,26 @@ impl Option { } } + /// Returns `None` if the option is `None`, otherwise calls `f` with a + /// reference to the wrapped value and returns the result. + #[inline] + pub fn and_then_ref<'a, U>(&'a self, f: &fn(&'a T) -> Option) -> Option { + match *self { + Some(ref x) => f(x), + None => None + } + } + + /// Returns `None` if the option is `None`, otherwise calls `f` with a + /// mutable reference to the wrapped value and returns the result. + #[inline] + pub fn and_then_mut_ref<'a, U>(&'a mut self, f: &fn(&'a mut T) -> Option) -> Option { + match *self { + Some(ref mut x) => f(x), + None => None + } + } + /// Returns the option if it contains a value, otherwise returns `optb`. #[inline] pub fn or(self, optb: Option) -> Option { @@ -157,8 +177,8 @@ impl Option { } } - /// Returns the option if it contains a value, otherwise calls and returns the - /// value of `f`. + /// Returns the option if it contains a value, otherwise calls `f` and + /// returns the result. #[inline] pub fn or_else(self, f: &fn() -> Option) -> Option { match self { From 28eb49bfbf7c7e4ece981bc3434e0809890304d6 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 13 Sep 2013 06:58:46 -0700 Subject: [PATCH 20/21] std: rename Option.chain to Option.and_then on windows --- src/libstd/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 95a75b849233..3a53edd11686 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -569,7 +569,7 @@ pub fn homedir() -> Option { #[cfg(windows)] fn secondary() -> Option { - do getenv("USERPROFILE").chain |p| { + do getenv("USERPROFILE").and_then |p| { if !p.is_empty() { Some(Path(p)) } else { From 93683ae6da3a47f1cd0644a093cb4b1b0bee7faa Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 13 Sep 2013 07:09:32 -0700 Subject: [PATCH 21/21] std: Fix another windows problem with the unwrap_or_default rename --- src/libstd/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 3a53edd11686..aeeae2072041 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -620,7 +620,7 @@ pub fn tmpdir() -> Path { getenv_nonempty("TMP").or( getenv_nonempty("TEMP").or( getenv_nonempty("USERPROFILE").or( - getenv_nonempty("WINDIR")))).unwrap_or_default(Path("C:\\Windows")) + getenv_nonempty("WINDIR")))).unwrap_or(Path("C:\\Windows")) } }