diff options
Diffstat (limited to 'src')
24 files changed, 614 insertions, 128 deletions
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index c2f6fbc0b26..04a692cc3ae 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -1143,15 +1143,39 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { } impl<'a, K: Ord, V> Entry<'a, K, V> { - /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant #[unstable(feature = "std_misc", reason = "will soon be replaced by or_insert")] + #[deprecated(since = "1.0", + reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")] + /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => Err(entry), } } + + #[unstable(feature = "collections", + reason = "matches entry v3 specification, waiting for dust to settle")] + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default), + } + } + + #[unstable(feature = "collections", + reason = "matches entry v3 specification, waiting for dust to settle")] + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default()), + } + } } impl<'a, K: Ord, V> VacantEntry<'a, K, V> { @@ -1563,21 +1587,12 @@ impl<K: Ord, V> BTreeMap<K, V> { /// ``` /// # #![feature(collections)] /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; /// /// let mut count: BTreeMap<&str, usize> = BTreeMap::new(); /// /// // count the number of occurrences of letters in the vec - /// for x in vec!["a","b","a","c","a","b"].iter() { - /// match count.entry(*x) { - /// Entry::Vacant(view) => { - /// view.insert(1); - /// }, - /// Entry::Occupied(mut view) => { - /// let v = view.get_mut(); - /// *v += 1; - /// }, - /// } + /// for x in vec!["a","b","a","c","a","b"] { + /// *count.entry(x).or_insert(0) += 1; /// } /// /// assert_eq!(count["a"], 3); diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index c994064d347..58f9101d1d3 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -632,21 +632,12 @@ impl<V> VecMap<V> { /// ``` /// # #![feature(collections)] /// use std::collections::VecMap; - /// use std::collections::vec_map::Entry; /// /// let mut count: VecMap<u32> = VecMap::new(); /// /// // count the number of occurrences of numbers in the vec - /// for x in vec![1, 2, 1, 2, 3, 4, 1, 2, 4].iter() { - /// match count.entry(*x) { - /// Entry::Vacant(view) => { - /// view.insert(1); - /// }, - /// Entry::Occupied(mut view) => { - /// let v = view.get_mut(); - /// *v += 1; - /// }, - /// } + /// for x in vec![1, 2, 1, 2, 3, 4, 1, 2, 4] { + /// *count.entry(x).or_insert(0) += 1; /// } /// /// assert_eq!(count[1], 3); @@ -675,6 +666,8 @@ impl<V> VecMap<V> { impl<'a, V> Entry<'a, V> { #[unstable(feature = "collections", reason = "will soon be replaced by or_insert")] + #[deprecated(since = "1.0", + reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, V>> { match self { @@ -682,6 +675,28 @@ impl<'a, V> Entry<'a, V> { Vacant(entry) => Err(entry), } } + + #[unstable(feature = "collections", + reason = "matches entry v3 specification, waiting for dust to settle")] + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default), + } + } + + #[unstable(feature = "collections", + reason = "matches entry v3 specification, waiting for dust to settle")] + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default()), + } + } } impl<'a, V> VacantEntry<'a, V> { diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 7854db81146..80fc3769453 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -426,8 +426,8 @@ impl<'a> Context<'a> { info!("lib candidate: {}", path.display()); let hash_str = hash.to_string(); - let slot = candidates.entry(hash_str).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert((HashMap::new(), HashMap::new()))); + let slot = candidates.entry(hash_str) + .or_insert_with(|| (HashMap::new(), HashMap::new())); let (ref mut rlibs, ref mut dylibs) = *slot; if rlib { rlibs.insert(fs::realpath(path).unwrap(), kind); diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index a1ce8d18184..0d58fd2702f 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -160,12 +160,7 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>, cfg.graph.each_node(|node_idx, node| { if let cfg::CFGNodeData::AST(id) = node.data { - match index.entry(id).get() { - Ok(v) => v.push(node_idx), - Err(e) => { - e.insert(vec![node_idx]); - } - } + index.entry(id).or_insert(vec![]).push(node_idx); } true }); @@ -185,12 +180,7 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>, visit::walk_fn_decl(&mut formals, decl); impl<'a, 'v> visit::Visitor<'v> for Formals<'a> { fn visit_pat(&mut self, p: &ast::Pat) { - match self.index.entry(p.id).get() { - Ok(v) => v.push(self.entry), - Err(e) => { - e.insert(vec![self.entry]); - } - } + self.index.entry(p.id).or_insert(vec![]).push(self.entry); visit::walk_pat(self, p) } } diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index c1066aa899e..3d46f93914a 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -11,7 +11,6 @@ use middle::infer::{InferCtxt}; use middle::ty::{self, RegionEscape, Ty}; use std::collections::HashSet; -use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::default::Default; use syntax::ast; use util::common::ErrorReported; @@ -437,9 +436,7 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("register_region_obligation({})", region_obligation.repr(tcx)); - match region_obligations.entry(region_obligation.cause.body_id) { - Vacant(entry) => { entry.insert(vec![region_obligation]); }, - Occupied(mut entry) => { entry.get_mut().push(region_obligation); }, - } + region_obligations.entry(region_obligation.cause.body_id).or_insert(vec![]) + .push(region_obligation); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 92b444e85d8..23fba5ead22 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -5669,9 +5669,7 @@ pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>, node_id_to_type(tcx, id.node) } else { let mut tcache = tcx.tcache.borrow_mut(); - let pty = tcache.entry(id).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert(csearch::get_field_type(tcx, struct_id, id))); - pty.ty + tcache.entry(id).or_insert_with(|| csearch::get_field_type(tcx, struct_id, id)).ty }; ty.subst(tcx, substs) } @@ -6819,9 +6817,7 @@ pub fn replace_late_bound_regions<'tcx, T, F>( debug!("region={}", region.repr(tcx)); match region { ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => { - let region = - * map.entry(br).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert(mapf(br))); + let region = *map.entry(br).or_insert_with(|| mapf(br)); if let ty::ReLateBound(debruijn1, br) = region { // If the callback returns a late-bound region, diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index a7c67a08631..931cfc79992 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -35,7 +35,6 @@ use syntax::parse::token::InternedString; use getopts; use std::collections::HashMap; -use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::env; use std::fmt; use std::path::PathBuf; @@ -1037,10 +1036,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { None => early_error("--extern value must be of the format `foo=bar`"), }; - match externs.entry(name.to_string()) { - Vacant(entry) => { entry.insert(vec![location.to_string()]); }, - Occupied(mut entry) => { entry.get_mut().push(location.to_string()); }, - } + externs.entry(name.to_string()).or_insert(vec![]).push(location.to_string()); } let crate_name = matches.opt_str("crate-name"); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 566af2590e6..5bf561c218d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -26,7 +26,6 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(std_misc)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 46451019760..662b5a36643 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -836,11 +836,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let is_public = import_directive.is_public; let mut import_resolutions = module_.import_resolutions.borrow_mut(); - let dest_import_resolution = import_resolutions.entry(name).get().unwrap_or_else( - |vacant_entry| { - // Create a new import resolution from this child. - vacant_entry.insert(ImportResolution::new(id, is_public)) - }); + let dest_import_resolution = import_resolutions.entry(name) + .or_insert_with(|| ImportResolution::new(id, is_public)); debug!("(resolving glob import) writing resolution `{}` in `{}` \ to `{}`", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1e38a7d2d9f..0f9836bc073 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -112,7 +112,6 @@ use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; use util::lev_distance::lev_distance; use std::cell::{Cell, Ref, RefCell}; -use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::mem::replace; use std::rc::Rc; use std::iter::repeat; @@ -1362,11 +1361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_def_id: ast::DefId, r: DeferredCallResolutionHandler<'tcx>) { let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut(); - let mut vec = match deferred_call_resolutions.entry(closure_def_id) { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(Vec::new()), - }; - vec.push(r); + deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r); } fn remove_deferred_call_resolutions(&self, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d57739c4002..d3612424794 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -876,9 +876,7 @@ impl DocFolder for Cache { if let clean::ImplItem(ref i) = item.inner { match i.trait_ { Some(clean::ResolvedPath{ did, .. }) => { - let v = self.implementors.entry(did).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert(Vec::with_capacity(1))); - v.push(Implementor { + self.implementors.entry(did).or_insert(vec![]).push(Implementor { def_id: item.def_id, generics: i.generics.clone(), trait_: i.trait_.as_ref().unwrap().clone(), @@ -1080,9 +1078,7 @@ impl DocFolder for Cache { }; if let Some(did) = did { - let v = self.impls.entry(did).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert(Vec::with_capacity(1))); - v.push(Impl { + self.impls.entry(did).or_insert(vec![]).push(Impl { impl_: i, dox: dox, stability: item.stability.clone(), @@ -1334,9 +1330,8 @@ impl Context { Some(ref s) => s.to_string(), }; let short = short.to_string(); - let v = map.entry(short).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert(Vec::with_capacity(1))); - v.push((myname, Some(plain_summary_line(item.doc_value())))); + map.entry(short).or_insert(vec![]) + .push((myname, Some(plain_summary_line(item.doc_value())))); } for (_, items) in &mut map { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 9f1d876432c..a85f770f63c 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -352,9 +352,7 @@ fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> { } }; let name = name.to_string(); - let locs = externs.entry(name).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert(Vec::with_capacity(1))); - locs.push(location.to_string()); + externs.entry(name).or_insert(vec![]).push(location.to_string()); } Ok(externs) } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index f9558b85825..91225891338 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -23,7 +23,7 @@ use hash::{Hash, SipHasher}; use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map}; use marker::Sized; use mem::{self, replace}; -use ops::{Deref, FnMut, Index}; +use ops::{Deref, FnMut, FnOnce, Index}; use option::Option::{self, Some, None}; use rand::{self, Rng}; use result::Result::{self, Ok, Err}; @@ -1488,12 +1488,37 @@ impl<'a, K, V> Entry<'a, K, V> { /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant. #[unstable(feature = "std_misc", reason = "will soon be replaced by or_insert")] + #[deprecated(since = "1.0", + reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")] + /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => Err(entry), } } + + #[unstable(feature = "collections", + reason = "matches entry v3 specification, waiting for dust to settle")] + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default), + } + } + + #[unstable(feature = "collections", + reason = "matches entry v3 specification, waiting for dust to settle")] + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default()), + } + } } impl<'a, K, V> OccupiedEntry<'a, K, V> { diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 8d24f6b1916..0ac97b71298 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -307,10 +307,7 @@ //! let message = "she sells sea shells by the sea shore"; //! //! for c in message.chars() { -//! match count.entry(c) { -//! Entry::Vacant(entry) => { entry.insert(1); }, -//! Entry::Occupied(mut entry) => *entry.get_mut() += 1, -//! } +//! *count.entry(c).or_insert(0) += 1; //! } //! //! assert_eq!(count.get(&'s'), Some(&8)); @@ -343,10 +340,7 @@ //! for id in orders.into_iter() { //! // If this is the first time we've seen this customer, initialize them //! // with no blood alcohol. Otherwise, just retrieve them. -//! let person = match blood_alcohol.entry(id) { -//! Entry::Vacant(entry) => entry.insert(Person{id: id, blood_alcohol: 0.0}), -//! Entry::Occupied(entry) => entry.into_mut(), -//! }; +//! let person = blood_alcohol.entry(id).or_insert(Person{id: id, blood_alcohol: 0.0}); //! //! // Reduce their blood alcohol level. It takes time to order and drink a beer! //! person.blood_alcohol *= 0.9; diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 16298240acf..ce03e26866b 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -24,38 +24,58 @@ use vec::Vec; #[stable(feature = "rust1", since = "1.0.0")] impl<'a, R: Read + ?Sized> Read for &'a mut R { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { (**self).read(buf) } + + #[inline] fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { (**self).read_to_end(buf) } + + #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { (**self).read_to_string(buf) } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, W: Write + ?Sized> Write for &'a mut W { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) } + + #[inline] fn flush(&mut self) -> io::Result<()> { (**self).flush() } + + #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (**self).write_all(buf) } + + #[inline] fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { (**self).write_fmt(fmt) } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, S: Seek + ?Sized> Seek for &'a mut S { + #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B { + #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } + + #[inline] fn consume(&mut self, amt: usize) { (**self).consume(amt) } + + #[inline] fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> { (**self).read_until(byte, buf) } + + #[inline] fn read_line(&mut self, buf: &mut String) -> io::Result<usize> { (**self).read_line(buf) } @@ -63,38 +83,58 @@ impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B { #[stable(feature = "rust1", since = "1.0.0")] impl<R: Read + ?Sized> Read for Box<R> { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { (**self).read(buf) } + + #[inline] fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { (**self).read_to_end(buf) } + + #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { (**self).read_to_string(buf) } } #[stable(feature = "rust1", since = "1.0.0")] impl<W: Write + ?Sized> Write for Box<W> { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) } + + #[inline] fn flush(&mut self) -> io::Result<()> { (**self).flush() } + + #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (**self).write_all(buf) } + + #[inline] fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { (**self).write_fmt(fmt) } } #[stable(feature = "rust1", since = "1.0.0")] impl<S: Seek + ?Sized> Seek for Box<S> { + #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) } } #[stable(feature = "rust1", since = "1.0.0")] impl<B: BufRead + ?Sized> BufRead for Box<B> { + #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } + + #[inline] fn consume(&mut self, amt: usize) { (**self).consume(amt) } + + #[inline] fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> { (**self).read_until(byte, buf) } + + #[inline] fn read_line(&mut self, buf: &mut String) -> io::Result<usize> { (**self).read_line(buf) } @@ -105,6 +145,7 @@ impl<B: BufRead + ?Sized> BufRead for Box<B> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a [u8] { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { let amt = cmp::min(buf.len(), self.len()); let (a, b) = self.split_at(amt); @@ -116,12 +157,16 @@ impl<'a> Read for &'a [u8] { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for &'a [u8] { + #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) } + + #[inline] fn consume(&mut self, amt: usize) { *self = &self[amt..]; } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a mut [u8] { + #[inline] fn write(&mut self, data: &[u8]) -> io::Result<usize> { let amt = cmp::min(data.len(), self.len()); let (a, b) = mem::replace(self, &mut []).split_at_mut(amt); @@ -130,6 +175,7 @@ impl<'a> Write for &'a mut [u8] { Ok(amt) } + #[inline] fn write_all(&mut self, data: &[u8]) -> io::Result<()> { if try!(self.write(data)) == data.len() { Ok(()) @@ -138,20 +184,87 @@ impl<'a> Write for &'a mut [u8] { } } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for Vec<u8> { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.push_all(buf); Ok(buf.len()) } + #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.push_all(buf); Ok(()) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } + +#[cfg(test)] +mod tests { + use io::prelude::*; + use vec::Vec; + use test; + + #[bench] + fn bench_read_slice(b: &mut test::Bencher) { + let buf = [5; 1024]; + let mut dst = [0; 128]; + + b.iter(|| { + let mut rd = &buf[..]; + for _ in (0 .. 8) { + let _ = rd.read(&mut dst); + test::black_box(&dst); + } + }) + } + + #[bench] + fn bench_write_slice(b: &mut test::Bencher) { + let mut buf = [0; 1024]; + let src = [5; 128]; + + b.iter(|| { + let mut wr = &mut buf[..]; + for _ in (0 .. 8) { + let _ = wr.write_all(&src); + test::black_box(&wr); + } + }) + } + + #[bench] + fn bench_read_vec(b: &mut test::Bencher) { + let buf = vec![5; 1024]; + let mut dst = [0; 128]; + + b.iter(|| { + let mut rd = &buf[..]; + for _ in (0 .. 8) { + let _ = rd.read(&mut dst); + test::black_box(&dst); + } + }) + } + + #[bench] + fn bench_write_vec(b: &mut test::Bencher) { + let mut buf = Vec::with_capacity(1024); + let src = [5; 128]; + + b.iter(|| { + let mut wr = &mut buf[..]; + for _ in (0 .. 8) { + let _ = wr.write_all(&src); + test::black_box(&wr); + } + }) + } +} diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 58b6d96607d..0c5e4d67642 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -332,6 +332,46 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) RefCell::new(f) } +/// This method helps to extract all the type parameters referenced from a +/// type. For a type parameter `<T>`, it looks for either a `TyPath` that +/// is not global and starts with `T`, or a `TyQPath`. +fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast::Ty>> { + use visit; + + struct Visitor<'a> { + ty_param_names: &'a [ast::Name], + types: Vec<P<ast::Ty>>, + } + + impl<'a> visit::Visitor<'a> for Visitor<'a> { + fn visit_ty(&mut self, ty: &'a ast::Ty) { + match ty.node { + ast::TyPath(_, ref path) if !path.global => { + match path.segments.first() { + Some(segment) => { + if self.ty_param_names.contains(&segment.identifier.name) { + self.types.push(P(ty.clone())); + } + } + None => {} + } + } + _ => {} + } + + visit::walk_ty(self, ty) + } + } + + let mut visitor = Visitor { + ty_param_names: ty_param_names, + types: Vec::new(), + }; + + visit::Visitor::visit_ty(&mut visitor, ty); + + visitor.types +} impl<'a> TraitDef<'a> { pub fn expand<F>(&self, @@ -374,18 +414,42 @@ impl<'a> TraitDef<'a> { })) } - /// Given that we are deriving a trait `Tr` for a type `T<'a, ..., - /// 'z, A, ..., Z>`, creates an impl like: + /// Given that we are deriving a trait `DerivedTrait` for a type like: /// /// ```ignore - /// impl<'a, ..., 'z, A:Tr B1 B2, ..., Z: Tr B1 B2> Tr for T<A, ..., Z> { ... } + /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait { + /// a: A, + /// b: B::Item, + /// b1: <B as DeclaredTrait>::Item, + /// c1: <C as WhereTrait>::Item, + /// c2: Option<<C as WhereTrait>::Item>, + /// ... + /// } + /// ``` + /// + /// create an impl like: + /// + /// ```ignore + /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where + /// C: WhereTrait, + /// A: DerivedTrait + B1 + ... + BN, + /// B: DerivedTrait + B1 + ... + BN, + /// C: DerivedTrait + B1 + ... + BN, + /// B::Item: DerivedTrait + B1 + ... + BN, + /// <C as WhereTrait>::Item: DerivedTrait + B1 + ... + BN, + /// ... + /// { + /// ... + /// } /// ``` /// - /// where B1, B2, ... are the bounds given by `bounds_paths`.' + /// where B1, ..., BN are the bounds given by `bounds_paths`.'. Z is a phantom type, and + /// therefore does not get bound by the derived trait. fn create_derived_impl(&self, cx: &mut ExtCtxt, type_ident: Ident, generics: &Generics, + field_tys: Vec<P<ast::Ty>>, methods: Vec<P<ast::ImplItem>>) -> P<ast::Item> { let trait_path = self.path.to_path(cx, self.span, type_ident, generics); @@ -466,6 +530,35 @@ impl<'a> TraitDef<'a> { } })); + if !ty_params.is_empty() { + let ty_param_names: Vec<ast::Name> = ty_params.iter() + .map(|ty_param| ty_param.ident.name) + .collect(); + + for field_ty in field_tys.into_iter() { + let tys = find_type_parameters(&*field_ty, &ty_param_names); + + for ty in tys.into_iter() { + let mut bounds: Vec<_> = self.additional_bounds.iter().map(|p| { + cx.typarambound(p.to_path(cx, self.span, type_ident, generics)) + }).collect(); + + // require the current trait + bounds.push(cx.typarambound(trait_path.clone())); + + let predicate = ast::WhereBoundPredicate { + span: self.span, + bound_lifetimes: vec![], + bounded_ty: ty, + bounds: OwnedSlice::from_vec(bounds), + }; + + let predicate = ast::WherePredicate::BoundPredicate(predicate); + where_clause.predicates.push(predicate); + } + } + } + let trait_generics = Generics { lifetimes: lifetimes, ty_params: OwnedSlice::from_vec(ty_params), @@ -518,6 +611,10 @@ impl<'a> TraitDef<'a> { struct_def: &StructDef, type_ident: Ident, generics: &Generics) -> P<ast::Item> { + let field_tys: Vec<P<ast::Ty>> = struct_def.fields.iter() + .map(|field| field.node.ty.clone()) + .collect(); + let methods = self.methods.iter().map(|method_def| { let (explicit_self, self_args, nonself_args, tys) = method_def.split_self_nonself_args( @@ -550,7 +647,7 @@ impl<'a> TraitDef<'a> { body) }).collect(); - self.create_derived_impl(cx, type_ident, generics, methods) + self.create_derived_impl(cx, type_ident, generics, field_tys, methods) } fn expand_enum_def(&self, @@ -558,6 +655,21 @@ impl<'a> TraitDef<'a> { enum_def: &EnumDef, type_ident: Ident, generics: &Generics) -> P<ast::Item> { + let mut field_tys = Vec::new(); + + for variant in enum_def.variants.iter() { + match variant.node.kind { + ast::VariantKind::TupleVariantKind(ref args) => { + field_tys.extend(args.iter() + .map(|arg| arg.ty.clone())); + } + ast::VariantKind::StructVariantKind(ref args) => { + field_tys.extend(args.fields.iter() + .map(|field| field.node.ty.clone())); + } + } + } + let methods = self.methods.iter().map(|method_def| { let (explicit_self, self_args, nonself_args, tys) = method_def.split_self_nonself_args(cx, self, @@ -590,7 +702,7 @@ impl<'a> TraitDef<'a> { body) }).collect(); - self.create_derived_impl(cx, type_ident, generics, methods) + self.create_derived_impl(cx, type_ident, generics, field_tys, methods) } } diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index 72431d8e6aa..a2023d6832e 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -66,9 +66,8 @@ pub fn apply_mark(m: Mrk, ctxt: SyntaxContext) -> SyntaxContext { /// Extend a syntax context with a given mark and sctable (explicit memoization) fn apply_mark_internal(m: Mrk, ctxt: SyntaxContext, table: &SCTable) -> SyntaxContext { let key = (ctxt, m); - * table.mark_memo.borrow_mut().entry(key).get().unwrap_or_else( - |vacant_entry| - vacant_entry.insert(idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt)))) + * table.mark_memo.borrow_mut().entry(key) + .or_insert_with(|| idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt))) } /// Extend a syntax context with a given rename @@ -84,9 +83,8 @@ fn apply_rename_internal(id: Ident, table: &SCTable) -> SyntaxContext { let key = (ctxt, id, to); - * table.rename_memo.borrow_mut().entry(key).get().unwrap_or_else( - |vacant_entry| - vacant_entry.insert(idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt)))) + * table.rename_memo.borrow_mut().entry(key) + .or_insert_with(|| idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt))) } /// Apply a list of renamings to a context diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index a25a6451918..5bbcdea879d 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -171,10 +171,12 @@ pub mod rt { } } + impl_to_source! { ast::Path, path_to_string } impl_to_source! { ast::Ty, ty_to_string } impl_to_source! { ast::Block, block_to_string } impl_to_source! { ast::Arg, arg_to_string } impl_to_source! { Generics, generics_to_string } + impl_to_source! { ast::WhereClause, where_clause_to_string } impl_to_source! { P<ast::Item>, item_to_string } impl_to_source! { P<ast::ImplItem>, impl_item_to_string } impl_to_source! { P<ast::TraitItem>, trait_item_to_string } @@ -310,6 +312,7 @@ pub mod rt { } impl_to_tokens! { ast::Ident } + impl_to_tokens! { ast::Path } impl_to_tokens! { P<ast::Item> } impl_to_tokens! { P<ast::ImplItem> } impl_to_tokens! { P<ast::TraitItem> } @@ -319,6 +322,7 @@ pub mod rt { impl_to_tokens! { ast::Ty } impl_to_tokens_lifetime! { &'a [ast::Ty] } impl_to_tokens! { Generics } + impl_to_tokens! { ast::WhereClause } impl_to_tokens! { P<ast::Stmt> } impl_to_tokens! { P<ast::Expr> } impl_to_tokens! { ast::Block } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 9af7b9ab633..72498afa320 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -35,7 +35,6 @@ #![feature(quote, unsafe_destructor)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(std_misc)] #![feature(unicode)] #![feature(path_ext)] #![feature(str_char)] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 220ea30256e..786970ce252 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1126,7 +1126,7 @@ impl<'a> Parser<'a> { p.parse_arg_general(false) }); - p.parse_where_clause(&mut generics); + generics.where_clause = p.parse_where_clause(); let sig = ast::MethodSig { unsafety: style, decl: d, @@ -3932,9 +3932,14 @@ impl<'a> Parser<'a> { /// ``` /// where T : Trait<U, V> + 'b, 'a : 'b /// ``` - fn parse_where_clause(&mut self, generics: &mut ast::Generics) { + fn parse_where_clause(&mut self) -> ast::WhereClause { + let mut where_clause = WhereClause { + id: ast::DUMMY_NODE_ID, + predicates: Vec::new(), + }; + if !self.eat_keyword(keywords::Where) { - return + return where_clause; } let mut parsed_something = false; @@ -3957,7 +3962,7 @@ impl<'a> Parser<'a> { let hi = self.span.hi; let span = mk_sp(lo, hi); - generics.where_clause.predicates.push(ast::WherePredicate::RegionPredicate( + where_clause.predicates.push(ast::WherePredicate::RegionPredicate( ast::WhereRegionPredicate { span: span, lifetime: bounded_lifetime, @@ -3992,7 +3997,7 @@ impl<'a> Parser<'a> { at least one bound in it"); } - generics.where_clause.predicates.push(ast::WherePredicate::BoundPredicate( + where_clause.predicates.push(ast::WherePredicate::BoundPredicate( ast::WhereBoundPredicate { span: span, bound_lifetimes: bound_lifetimes, @@ -4005,7 +4010,7 @@ impl<'a> Parser<'a> { // let ty = self.parse_ty(); let hi = self.span.hi; let span = mk_sp(lo, hi); - // generics.where_clause.predicates.push( + // where_clause.predicates.push( // ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { // id: ast::DUMMY_NODE_ID, // span: span, @@ -4036,6 +4041,8 @@ impl<'a> Parser<'a> { "a `where` clause must have at least one predicate \ in it"); } + + where_clause } fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) @@ -4354,7 +4361,7 @@ impl<'a> Parser<'a> { fn parse_item_fn(&mut self, unsafety: Unsafety, abi: abi::Abi) -> ItemInfo { let (ident, mut generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(false); - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); let (inner_attrs, body) = self.parse_inner_attrs_and_block(); (ident, ItemFn(decl, unsafety, abi, generics, body), Some(inner_attrs)) } @@ -4439,7 +4446,7 @@ impl<'a> Parser<'a> { let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| { p.parse_arg() }); - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); let (inner_attrs, body) = self.parse_inner_attrs_and_block(); (ident, inner_attrs, MethodImplItem(ast::MethodSig { generics: generics, @@ -4460,7 +4467,7 @@ impl<'a> Parser<'a> { // Parse supertrait bounds. let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare); - self.parse_where_clause(&mut tps); + tps.where_clause = self.parse_where_clause(); let meths = self.parse_trait_items(); (ident, ItemTrait(unsafety, tps, bounds, meths), None) @@ -4531,7 +4538,7 @@ impl<'a> Parser<'a> { if opt_trait.is_some() { ty = self.parse_ty_sum(); } - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); self.expect(&token::OpenDelim(token::Brace)); let attrs = self.parse_inner_attributes(); @@ -4603,7 +4610,7 @@ impl<'a> Parser<'a> { // struct. let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) { - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); if self.eat(&token::Semi) { // If we see a: `struct Foo<T> where T: Copy;` style decl. (Vec::new(), Some(ast::DUMMY_NODE_ID)) @@ -4684,12 +4691,12 @@ impl<'a> Parser<'a> { token::get_ident(class_name.clone()))); } - self.parse_where_clause(generics); + generics.where_clause = self.parse_where_clause(); self.expect(&token::Semi); fields // This is the case where we just see struct Foo<T> where T: Copy; } else if self.token.is_keyword(keywords::Where) { - self.parse_where_clause(generics); + generics.where_clause = self.parse_where_clause(); self.expect(&token::Semi); Vec::new() // This case is where we see: `struct Foo<T>;` @@ -4937,7 +4944,7 @@ impl<'a> Parser<'a> { let (ident, mut generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(true); - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); let hi = self.span.hi; self.expect(&token::Semi); P(ast::ForeignItem { @@ -5074,7 +5081,7 @@ impl<'a> Parser<'a> { fn parse_item_type(&mut self) -> ItemInfo { let ident = self.parse_ident(); let mut tps = self.parse_generics(); - self.parse_where_clause(&mut tps); + tps.where_clause = self.parse_where_clause(); self.expect(&token::Eq); let ty = self.parse_ty_sum(); self.expect(&token::Semi); @@ -5174,7 +5181,7 @@ impl<'a> Parser<'a> { fn parse_item_enum(&mut self) -> ItemInfo { let id = self.parse_ident(); let mut generics = self.parse_generics(); - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); self.expect(&token::OpenDelim(token::Brace)); let enum_definition = self.parse_enum_def(&generics); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 2bc3fc1017a..da1b7a7bdde 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -367,6 +367,10 @@ pub fn generics_to_string(generics: &ast::Generics) -> String { $to_string(|s| s.print_generics(generics)) } +pub fn where_clause_to_string(i: &ast::WhereClause) -> String { + $to_string(|s| s.print_where_clause(i)) +} + pub fn fn_block_to_string(p: &ast::FnDecl) -> String { $to_string(|s| s.print_fn_block_args(p)) } @@ -917,7 +921,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.word_space("=")); try!(self.print_type(&**ty)); - try!(self.print_where_clause(params)); + try!(self.print_where_clause(¶ms.where_clause)); try!(word(&mut self.s, ";")); try!(self.end()); // end the outer ibox } @@ -980,7 +984,7 @@ impl<'a> State<'a> { } try!(self.print_type(&**ty)); - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(space(&mut self.s)); try!(self.bopen()); @@ -1008,7 +1012,7 @@ impl<'a> State<'a> { } } try!(self.print_bounds(":", &real_bounds[..])); - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(word(&mut self.s, " ")); try!(self.bopen()); for trait_item in trait_items { @@ -1066,7 +1070,7 @@ impl<'a> State<'a> { try!(self.head(&visibility_qualified(visibility, "enum"))); try!(self.print_ident(ident)); try!(self.print_generics(generics)); - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(space(&mut self.s)); self.print_variants(&enum_definition.variants, span) } @@ -1120,12 +1124,12 @@ impl<'a> State<'a> { )); try!(self.pclose()); } - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(word(&mut self.s, ";")); try!(self.end()); self.end() // close the outer-box } else { - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(self.nbsp()); try!(self.bopen()); try!(self.hardbreak_if_not_bol()); @@ -2348,7 +2352,7 @@ impl<'a> State<'a> { } try!(self.print_generics(generics)); try!(self.print_fn_args_and_ret(decl, opt_explicit_self)); - self.print_where_clause(generics) + self.print_where_clause(&generics.where_clause) } pub fn print_fn_args(&mut self, decl: &ast::FnDecl, @@ -2531,19 +2535,16 @@ impl<'a> State<'a> { } } - pub fn print_where_clause(&mut self, generics: &ast::Generics) + pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause) -> io::Result<()> { - if generics.where_clause.predicates.len() == 0 { + if where_clause.predicates.len() == 0 { return Ok(()) } try!(space(&mut self.s)); try!(self.word_space("where")); - for (i, predicate) in generics.where_clause - .predicates - .iter() - .enumerate() { + for (i, predicate) in where_clause.predicates.iter().enumerate() { if i != 0 { try!(self.word_space(",")); } diff --git a/src/test/auxiliary/struct_variant_xc_aux.rs b/src/test/auxiliary/struct_variant_xc_aux.rs index 76fd619f689..8670cd96fc6 100644 --- a/src/test/auxiliary/struct_variant_xc_aux.rs +++ b/src/test/auxiliary/struct_variant_xc_aux.rs @@ -11,6 +11,7 @@ #![crate_name="struct_variant_xc_aux"] #![crate_type = "lib"] +#[derive(Copy)] pub enum Enum { Variant(u8), StructVariant { arg: u8 } diff --git a/src/test/compile-fail/derive-assoc-type-not-impl.rs b/src/test/compile-fail/derive-assoc-type-not-impl.rs new file mode 100644 index 00000000000..3799f2ffba4 --- /dev/null +++ b/src/test/compile-fail/derive-assoc-type-not-impl.rs @@ -0,0 +1,29 @@ +// Copyright 2015 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + type X; + fn method(&self) {} +} + +#[derive(Clone)] +struct Bar<T: Foo> { + x: T::X, +} + +struct NotClone; + +impl Foo for NotClone { + type X = i8; +} + +fn main() { + Bar::<NotClone> { x: 1 }.clone(); //~ ERROR +} diff --git a/src/test/run-pass/deriving-associated-types.rs b/src/test/run-pass/deriving-associated-types.rs new file mode 100644 index 00000000000..59eb5506c45 --- /dev/null +++ b/src/test/run-pass/deriving-associated-types.rs @@ -0,0 +1,210 @@ +// Copyright 2015 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core, debug_builders)] + +pub trait DeclaredTrait { + type Type; +} + +impl DeclaredTrait for i32 { + type Type = i32; +} + +pub trait WhereTrait { + type Type; +} + +impl WhereTrait for i32 { + type Type = i32; +} + +// Make sure we don't add a bound that just shares a name with an associated +// type. +pub mod module { + pub type Type = i32; +} + +#[derive(PartialEq, Debug)] +struct PrivateStruct<T>(T); + +#[derive(PartialEq, Debug)] +struct TupleStruct<A, B: DeclaredTrait, C>( + module::Type, + Option<module::Type>, + A, + PrivateStruct<A>, + B, + B::Type, + Option<B::Type>, + <B as DeclaredTrait>::Type, + Option<<B as DeclaredTrait>::Type>, + C, + C::Type, + Option<C::Type>, + <C as WhereTrait>::Type, + Option<<C as WhereTrait>::Type>, + <i32 as DeclaredTrait>::Type, +) where C: WhereTrait; + +#[derive(PartialEq, Debug)] +pub struct Struct<A, B: DeclaredTrait, C> where C: WhereTrait { + m1: module::Type, + m2: Option<module::Type>, + a1: A, + a2: PrivateStruct<A>, + b: B, + b1: B::Type, + b2: Option<B::Type>, + b3: <B as DeclaredTrait>::Type, + b4: Option<<B as DeclaredTrait>::Type>, + c: C, + c1: C::Type, + c2: Option<C::Type>, + c3: <C as WhereTrait>::Type, + c4: Option<<C as WhereTrait>::Type>, + d: <i32 as DeclaredTrait>::Type, +} + +#[derive(PartialEq, Debug)] +enum Enum<A, B: DeclaredTrait, C> where C: WhereTrait { + Unit, + Seq( + module::Type, + Option<module::Type>, + A, + PrivateStruct<A>, + B, + B::Type, + Option<B::Type>, + <B as DeclaredTrait>::Type, + Option<<B as DeclaredTrait>::Type>, + C, + C::Type, + Option<C::Type>, + <C as WhereTrait>::Type, + Option<<C as WhereTrait>::Type>, + <i32 as DeclaredTrait>::Type, + ), + Map { + m1: module::Type, + m2: Option<module::Type>, + a1: A, + a2: PrivateStruct<A>, + b: B, + b1: B::Type, + b2: Option<B::Type>, + b3: <B as DeclaredTrait>::Type, + b4: Option<<B as DeclaredTrait>::Type>, + c: C, + c1: C::Type, + c2: Option<C::Type>, + c3: <C as WhereTrait>::Type, + c4: Option<<C as WhereTrait>::Type>, + d: <i32 as DeclaredTrait>::Type, + }, +} + +fn main() { + let e: TupleStruct< + i32, + i32, + i32, + > = TupleStruct( + 0, + None, + 0, + PrivateStruct(0), + 0, + 0, + None, + 0, + None, + 0, + 0, + None, + 0, + None, + 0, + ); + assert_eq!(e, e); + + let e: Struct< + i32, + i32, + i32, + > = Struct { + m1: 0, + m2: None, + a1: 0, + a2: PrivateStruct(0), + b: 0, + b1: 0, + b2: None, + b3: 0, + b4: None, + c: 0, + c1: 0, + c2: None, + c3: 0, + c4: None, + d: 0, + }; + assert_eq!(e, e); + + let e = Enum::Unit::<i32, i32, i32>; + assert_eq!(e, e); + + let e: Enum< + i32, + i32, + i32, + > = Enum::Seq( + 0, + None, + 0, + PrivateStruct(0), + 0, + 0, + None, + 0, + None, + 0, + 0, + None, + 0, + None, + 0, + ); + assert_eq!(e, e); + + let e: Enum< + i32, + i32, + i32, + > = Enum::Map { + m1: 0, + m2: None, + a1: 0, + a2: PrivateStruct(0), + b: 0, + b1: 0, + b2: None, + b3: 0, + b4: None, + c: 0, + c1: 0, + c2: None, + c3: 0, + c4: None, + d: 0, + }; + assert_eq!(e, e); +} |
