diff --git a/src/doc/trpl/pointers.md b/src/doc/trpl/pointers.md index bd9b449fc087e..107d7d979a09c 100644 --- a/src/doc/trpl/pointers.md +++ b/src/doc/trpl/pointers.md @@ -568,8 +568,8 @@ fn add(x: &i32, y: &i32) -> i32 { fn main() { let x = Box::new(5); - println!("{}", add(&x, &x)); - println!("{}", add(&x, &x)); + println!("{}", add(&*x, &*x)); + println!("{}", add(&*x, &*x)); } ``` diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 688d730e25287..83e632e6c9676 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -611,9 +611,11 @@ impl [T] { core_slice::SliceExt::get_mut(self, index) } - /// Work with `self` as a mut slice. - /// Primarily intended for getting a &mut [T] from a [T; N]. - #[stable(feature = "rust1", since = "1.0.0")] + /// Deprecated: use `&mut s[..]` instead. + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] + #[allow(deprecated)] pub fn as_mut_slice(&mut self) -> &mut [T] { core_slice::SliceExt::as_mut_slice(self) } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index e71077c96c774..19b0d5b166786 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -423,24 +423,13 @@ impl Vec { } } - /// Returns a mutable slice of the elements of `self`. - /// - /// # Examples - /// - /// ``` - /// fn foo(slice: &mut [i32]) {} - /// - /// let mut vec = vec![1, 2]; - /// foo(vec.as_mut_slice()); - /// ``` + /// Deprecated: use `&mut s[..]` instead. #[inline] - #[stable(feature = "rust1", since = "1.0.0")] + #[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] pub fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { - let ptr = *self.ptr; - assume(!ptr.is_null()); - slice::from_raw_parts_mut(ptr, self.len) - } + &mut self[..] } /// Creates a consuming iterator, that is, one that moves each value out of @@ -1494,13 +1483,13 @@ impl ops::IndexMut for Vec { #[cfg(stage0)] #[inline] fn index_mut(&mut self, _index: &ops::RangeFull) -> &mut [T] { - self.as_mut_slice() + self } #[cfg(not(stage0))] #[inline] fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [T] { - self.as_mut_slice() + self } } @@ -1519,7 +1508,13 @@ impl ops::Deref for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl ops::DerefMut for Vec { - fn deref_mut(&mut self) -> &mut [T] { self.as_mut_slice() } + fn deref_mut(&mut self) -> &mut [T] { + unsafe { + let ptr = *self.ptr; + assume(!ptr.is_null()); + slice::from_raw_parts_mut(ptr, self.len) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1656,21 +1651,13 @@ impl Ord for Vec { } } +#[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] +#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] #[allow(deprecated)] impl AsSlice for Vec { - /// Returns a slice into `self`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// fn foo(slice: &[i32]) {} - /// - /// let vec = vec![1, 2]; - /// foo(vec.as_slice()); - /// ``` + /// Deprecated: use `&mut s[..]` instead. #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn as_slice(&self) -> &[T] { self } diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index fce29abed7300..892660b98bc95 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -88,6 +88,9 @@ pub trait SliceExt { fn len(&self) -> usize; fn is_empty(&self) -> bool { self.len() == 0 } fn get_mut<'a>(&'a mut self, index: usize) -> Option<&'a mut Self::Item>; + #[unstable(feature = "core", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item]; fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>; fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; @@ -261,6 +264,9 @@ impl SliceExt for [T] { } #[inline] + #[unstable(feature = "core", + reason = "will be replaced by slice syntax")] + #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] fn as_mut_slice(&mut self) -> &mut [T] { self } #[cfg(stage0)] diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 16298240acfbe..ce03e26866b7d 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 { (**self).read(buf) } + + #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (**self).read_to_end(buf) } + + #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { (**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 { (**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 { (**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) -> io::Result { (**self).read_until(byte, buf) } + + #[inline] fn read_line(&mut self, buf: &mut String) -> io::Result { (**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 Read for Box { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } + + #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (**self).read_to_end(buf) } + + #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { (**self).read_to_string(buf) } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for Box { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (**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 Seek for Box { + #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } } #[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Box { + #[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) -> io::Result { (**self).read_until(byte, buf) } + + #[inline] fn read_line(&mut self, buf: &mut String) -> io::Result { (**self).read_line(buf) } @@ -105,6 +145,7 @@ impl BufRead for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a [u8] { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { 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 { 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 { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { 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/libstd/net/addr.rs b/src/libstd/net/addr.rs index e8187dc2c4027..dafca974bec0e 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -15,7 +15,7 @@ use hash; use io; use libc::{self, socklen_t, sa_family_t}; use mem; -use net::{lookup_host, ntoh, hton, Ipv4Addr, Ipv6Addr}; +use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr}; use option; use sys_common::{FromInner, AsInner, IntoInner}; use vec; @@ -47,6 +47,15 @@ pub struct SocketAddrV4 { inner: libc::sockaddr_in } pub struct SocketAddrV6 { inner: libc::sockaddr_in6 } impl SocketAddr { + /// Gets the IP address associated with this socket address. + #[unstable(feature = "ip_addr", reason = "recent addition")] + pub fn ip(&self) -> IpAddr { + match *self { + SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), + SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), + } + } + /// Gets the port number associated with this socket address #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { @@ -333,6 +342,18 @@ impl ToSocketAddrs for SocketAddrV6 { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for (IpAddr, u16) { + type Iter = option::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + let (ip, port) = *self; + match ip { + IpAddr::V4(ref a) => (*a, port).to_socket_addrs(), + IpAddr::V6(ref a) => (*a, port).to_socket_addrs(), + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for (Ipv4Addr, u16) { type Iter = option::IntoIter; diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index d737ad17ff8ec..c8b1928747705 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -21,6 +21,16 @@ use libc; use sys_common::{AsInner, FromInner}; use net::{hton, ntoh}; +/// An IP address, either a IPv4 or IPv6 address. +#[unstable(feature = "ip_addr", reason = "recent addition")] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)] +pub enum IpAddr { + /// Representation of an IPv4 address. + V4(Ipv4Addr), + /// Representation of an IPv6 address. + V6(Ipv6Addr), +} + /// Representation of an IPv4 address. #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] @@ -139,6 +149,16 @@ impl Ipv4Addr { } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + IpAddr::V4(ref a) => a.fmt(fmt), + IpAddr::V6(ref a) => a.fmt(fmt), + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index 48b3247f2127a..7f51b1cba3fe7 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -21,7 +21,7 @@ use io::{self, Error, ErrorKind}; use num::Int; use sys_common::net2 as net_imp; -pub use self::ip::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; +pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; pub use self::tcp::{TcpStream, TcpListener}; pub use self::udp::UdpSocket; @@ -74,10 +74,14 @@ fn each_addr(addr: A, mut f: F) -> io::Result } /// An iterator over `SocketAddr` values returned from a host lookup operation. -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] pub struct LookupHost(net_imp::LookupHost); -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] impl Iterator for LookupHost { type Item = io::Result; fn next(&mut self) -> Option> { self.0.next() } @@ -91,7 +95,7 @@ impl Iterator for LookupHost { /// # Examples /// /// ```no_run -/// # #![feature(net)] +/// # #![feature(lookup_host)] /// use std::net; /// /// # fn foo() -> std::io::Result<()> { @@ -101,7 +105,9 @@ impl Iterator for LookupHost { /// # Ok(()) /// # } /// ``` -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] pub fn lookup_host(host: &str) -> io::Result { net_imp::lookup_host(host).map(LookupHost) } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index e593bbe8e489b..811511149628e 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -14,7 +14,7 @@ use prelude::v1::*; use io::{self, Error, ErrorKind}; -use net::{ToSocketAddrs, SocketAddr}; +use net::{ToSocketAddrs, SocketAddr, IpAddr}; use sys_common::net2 as net_imp; use sys_common::AsInner; @@ -116,12 +116,12 @@ impl UdpSocket { } /// Joins a multicast IP address (becomes a member of it) - pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> { + pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> { self.0.join_multicast(multi) } /// Leaves a multicast IP address (drops membership from it) - pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> { + pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> { self.0.leave_multicast(multi) } diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index 25aeab1b4ff74..e213a86644fe1 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -14,7 +14,7 @@ use ffi::CString; use io::{self, Error, ErrorKind}; use libc::{self, c_int, c_char, c_void, socklen_t}; use mem; -use net::{SocketAddr, Shutdown}; +use net::{SocketAddr, Shutdown, IpAddr}; use sys::c; use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; use sys_common::{AsInner, FromInner, IntoInner}; @@ -334,39 +334,39 @@ impl UdpSocket { libc::IP_MULTICAST_LOOP, on as c_int) } - pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> { + pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> { match *multi { - SocketAddr::V4(..) => { + IpAddr::V4(..) => { self.set_membership(multi, libc::IP_ADD_MEMBERSHIP) } - SocketAddr::V6(..) => { + IpAddr::V6(..) => { self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP) } } } - pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> { + pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> { match *multi { - SocketAddr::V4(..) => { + IpAddr::V4(..) => { self.set_membership(multi, libc::IP_DROP_MEMBERSHIP) } - SocketAddr::V6(..) => { + IpAddr::V6(..) => { self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP) } } } - fn set_membership(&self, addr: &SocketAddr, opt: c_int) -> io::Result<()> { + fn set_membership(&self, addr: &IpAddr, opt: c_int) -> io::Result<()> { match *addr { - SocketAddr::V4(ref addr) => { + IpAddr::V4(ref addr) => { let mreq = libc::ip_mreq { - imr_multiaddr: *addr.ip().as_inner(), + imr_multiaddr: *addr.as_inner(), // interface == INADDR_ANY imr_interface: libc::in_addr { s_addr: 0x0 }, }; setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq) } - SocketAddr::V6(ref addr) => { + IpAddr::V6(ref addr) => { let mreq = libc::ip6_mreq { - ipv6mr_multiaddr: *addr.ip().as_inner(), + ipv6mr_multiaddr: *addr.as_inner(), ipv6mr_interface: 0, }; setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq) diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 58b6d96607df7..0c5e4d67642ac 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 ``, 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> { + use visit; + + struct Visitor<'a> { + ty_param_names: &'a [ast::Name], + types: Vec>, + } + + 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(&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 { ... } + /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait { + /// a: A, + /// b: B::Item, + /// b1: ::Item, + /// c1: ::Item, + /// c2: Option<::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, + /// ::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>, methods: Vec>) -> P { 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 = 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 { + let field_tys: Vec> = 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 { + 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/test/auxiliary/struct_variant_xc_aux.rs b/src/test/auxiliary/struct_variant_xc_aux.rs index 76fd619f68964..8670cd96fc6de 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 0000000000000..3799f2ffba440 --- /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 or the MIT license +// , 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 { + x: T::X, +} + +struct NotClone; + +impl Foo for NotClone { + type X = i8; +} + +fn main() { + Bar:: { 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 0000000000000..59eb5506c45c7 --- /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 or the MIT license +// , 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); + +#[derive(PartialEq, Debug)] +struct TupleStruct( + module::Type, + Option, + A, + PrivateStruct, + B, + B::Type, + Option, + ::Type, + Option<::Type>, + C, + C::Type, + Option, + ::Type, + Option<::Type>, + ::Type, +) where C: WhereTrait; + +#[derive(PartialEq, Debug)] +pub struct Struct where C: WhereTrait { + m1: module::Type, + m2: Option, + a1: A, + a2: PrivateStruct, + b: B, + b1: B::Type, + b2: Option, + b3: ::Type, + b4: Option<::Type>, + c: C, + c1: C::Type, + c2: Option, + c3: ::Type, + c4: Option<::Type>, + d: ::Type, +} + +#[derive(PartialEq, Debug)] +enum Enum where C: WhereTrait { + Unit, + Seq( + module::Type, + Option, + A, + PrivateStruct, + B, + B::Type, + Option, + ::Type, + Option<::Type>, + C, + C::Type, + Option, + ::Type, + Option<::Type>, + ::Type, + ), + Map { + m1: module::Type, + m2: Option, + a1: A, + a2: PrivateStruct, + b: B, + b1: B::Type, + b2: Option, + b3: ::Type, + b4: Option<::Type>, + c: C, + c1: C::Type, + c2: Option, + c3: ::Type, + c4: Option<::Type>, + d: ::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::; + 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); +}