diff --git a/src/liballoc/owned.rs b/src/liballoc/owned.rs index 6f5d329355623..94b8bee8cc9d2 100644 --- a/src/liballoc/owned.rs +++ b/src/liballoc/owned.rs @@ -16,6 +16,7 @@ use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; use core::default::Default; use core::fmt; use core::intrinsics; +use core::kinds::Send; use core::mem; use core::raw::TraitObject; use core::result::{Ok, Err, Result}; @@ -106,6 +107,34 @@ impl AnyOwnExt for Box { } } +/// Extension methods for an owning `Any+Send` trait object +pub trait AnySendOwnExt { + /// Returns the boxed value if it is of type `T`, or + /// `Err(Self)` if it isn't. + fn move_send(self) -> Result, Self>; +} + +impl AnySendOwnExt for Box { + #[inline] + fn move_send(self) -> Result, Box> { + if self.is::() { + unsafe { + // Get the raw representation of the trait object + let to: TraitObject = + *mem::transmute::<&Box, &TraitObject>(&self); + + // Prevent destructor on self being run + intrinsics::forget(self); + + // Extract the data pointer + Ok(mem::transmute(to.data)) + } + } else { + Err(self) + } + } +} + impl fmt::Show for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 3f4d3020815df..ec53ef93dc1dd 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -135,7 +135,8 @@ pub trait Iterator { /// let a = [0i]; /// let b = [1i]; /// let mut it = a.iter().zip(b.iter()); - /// assert_eq!(it.next().unwrap(), (&0, &1)); + /// let (x0, x1) = (0i, 1i); + /// assert_eq!(it.next().unwrap(), (&x0, &x1)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -202,8 +203,9 @@ pub trait Iterator { /// ```rust /// let a = [100i, 200]; /// let mut it = a.iter().enumerate(); - /// assert_eq!(it.next().unwrap(), (0, &100)); - /// assert_eq!(it.next().unwrap(), (1, &200)); + /// let (x100, x200) = (100i, 200i); + /// assert_eq!(it.next().unwrap(), (0, &x100)); + /// assert_eq!(it.next().unwrap(), (1, &x200)); /// assert!(it.next().is_none()); /// ``` #[inline] @@ -220,11 +222,11 @@ pub trait Iterator { /// ```rust /// let xs = [100i, 200, 300]; /// let mut it = xs.iter().map(|x| *x).peekable(); - /// assert_eq!(it.peek().unwrap(), &100); + /// assert_eq!(*it.peek().unwrap(), 100); /// assert_eq!(it.next().unwrap(), 100); /// assert_eq!(it.next().unwrap(), 200); - /// assert_eq!(it.peek().unwrap(), &300); - /// assert_eq!(it.peek().unwrap(), &300); + /// assert_eq!(*it.peek().unwrap(), 300); + /// assert_eq!(*it.peek().unwrap(), 300); /// assert_eq!(it.next().unwrap(), 300); /// assert!(it.peek().is_none()); /// assert!(it.next().is_none()); diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 7612add9b0570..33e0d0331be6c 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -352,17 +352,15 @@ fn search_for_vtable(vcx: &VtableContext, // the next impl. // // FIXME: document a bit more what this means - // - // FIXME(#5781) this should be mk_eqty not mk_subty let TypeAndSubsts { substs: substs, ty: for_ty } = impl_self_ty(vcx, span, impl_did); - match infer::mk_subty(vcx.infcx, - false, - infer::RelateSelfType(span), - ty, - for_ty) { + match infer::mk_eqty(vcx.infcx, + false, + infer::RelateSelfType(span), + ty, + for_ty) { Err(_) => continue, Ok(()) => () } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 844a37d366ee5..f374f1dc26795 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -84,16 +84,13 @@ pub trait Combine { fn tys(&self, a: ty::t, b: ty::t) -> cres; fn tps(&self, - space: subst::ParamSpace, + _: subst::ParamSpace, as_: &[ty::t], bs: &[ty::t]) - -> cres> - { - // FIXME(#5781) -- In general, we treat variance a bit wrong - // here. For historical reasons, we treat Self as - // contravariant and other tps as invariant. Both are wrong: - // Self may or may not be contravariant, and other tps do not - // need to be invariant. + -> cres> { + // FIXME -- In general, we treat variance a bit wrong + // here. For historical reasons, we treat tps and Self + // as invariant. This is overly conservative. if as_.len() != bs.len() { return Err(ty::terr_ty_param_size(expected_found(self, @@ -101,24 +98,11 @@ pub trait Combine { bs.len()))); } - match space { - subst::SelfSpace => { - result::fold(as_ - .iter() - .zip(bs.iter()) - .map(|(a, b)| self.contratys(*a, *b)), - Vec::new(), - |mut v, a| { v.push(a); v }) - } - - subst::TypeSpace | subst::FnSpace => { - try!(result::fold_(as_ - .iter() - .zip(bs.iter()) - .map(|(a, b)| eq_tys(self, *a, *b)))); - Ok(Vec::from_slice(as_)) - } - } + try!(result::fold_(as_ + .iter() + .zip(bs.iter()) + .map(|(a, b)| eq_tys(self, *a, *b)))); + Ok(Vec::from_slice(as_)) } fn substs(&self, diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index 3731990e61faa..0a60a5ce0e9fa 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -78,8 +78,8 @@ receiver position from being called via an object.) #### Trait variance and vtable resolution But traits aren't only used with objects. They're also used when -deciding whether a given impl satisfies a given trait bound (or should -be -- FIXME #5781). To set the scene here, imagine I had a function: +deciding whether a given impl satisfies a given trait bound. To set the +scene here, imagine I had a function: fn convertAll>(v: &[T]) { ... diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index e7fc3cedf5ec9..7e7f10f71783d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -140,7 +140,14 @@ fn runtest(test: &str, cratename: &str, libs: HashSet, should_fail: bool, let old = io::stdio::set_stderr(box w1); spawn(proc() { let mut p = io::ChanReader::new(rx); - let mut err = old.unwrap_or(box io::stderr() as Box); + let mut err = match old { + Some(old) => { + // Chop off the `Send` bound. + let old: Box = old; + old + } + None => box io::stderr() as Box, + }; io::util::copy(&mut p, &mut err).unwrap(); }); let emitter = diagnostic::EmitterWriter::new(box w2); diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index c03fbf302d754..cd5887b7add00 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -183,7 +183,10 @@ mod test { writer.write_be_u32(42).unwrap(); let wanted = vec![0u8, 0u8, 0u8, 42u8]; - let got = task::try(proc() { rx.recv() }).unwrap(); + let got = match task::try(proc() { rx.recv() }) { + Ok(got) => got, + Err(_) => fail!(), + }; assert_eq!(wanted, got); match writer.write_u8(1) { diff --git a/src/libstd/task.rs b/src/libstd/task.rs index dad241002f86c..8ccded6681b07 100644 --- a/src/libstd/task.rs +++ b/src/libstd/task.rs @@ -630,9 +630,11 @@ mod test { let mut reader = ChanReader::new(rx); let stdout = ChanWriter::new(tx); - TaskBuilder::new().stdout(box stdout as Box).try(proc() { - print!("Hello, world!"); - }).unwrap(); + let r = TaskBuilder::new().stdout(box stdout as Box) + .try(proc() { + print!("Hello, world!"); + }); + assert!(r.is_ok()); let output = reader.read_to_str().unwrap(); assert_eq!(output, "Hello, world!".to_string()); diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 16c463f0c96ff..90569bfc132c7 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -18,6 +18,7 @@ use std::fmt; use std::io; use std::iter::range; use std::string::String; +use term::WriterWrapper; use term; // maximum number of lines we will print for each error; arbitrary. @@ -281,7 +282,7 @@ pub struct EmitterWriter { } enum Destination { - Terminal(Box> + Send>), + Terminal(Box + Send>), Raw(Box), } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 80ece06df3add..34d60ddbe9db9 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -66,28 +66,52 @@ pub mod terminfo; #[cfg(windows)] mod win; +/// A hack to work around the fact that `Box` does not +/// currently implement `Writer`. +pub struct WriterWrapper { + wrapped: Box, +} + +impl Writer for WriterWrapper { + #[inline] + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + self.wrapped.write(buf) + } + + #[inline] + fn flush(&mut self) -> IoResult<()> { + self.wrapped.flush() + } +} + #[cfg(not(windows))] /// Return a Terminal wrapping stdout, or None if a terminal couldn't be /// opened. -pub fn stdout() -> Option> + Send>> { - let ti: Option>> - = Terminal::new(box std::io::stdout() as Box); - ti.map(|t| box t as Box + Send> + Send>) +pub fn stdout() -> Option + Send>> { + let ti: Option> + = Terminal::new(WriterWrapper { + wrapped: box std::io::stdout() as Box, + }); + ti.map(|t| box t as Box + Send>) } #[cfg(windows)] /// Return a Terminal wrapping stdout, or None if a terminal couldn't be /// opened. -pub fn stdout() -> Option + Send> + Send>> { - let ti: Option>> - = Terminal::new(box std::io::stdout() as Box); +pub fn stdout() -> Option + Send>> { + let ti: Option> + = Terminal::new(WriterWrapper { + wrapped: box std::io::stdout() as Box, + }); match ti { - Some(t) => Some(box t as Box + Send> + Send>), + Some(t) => Some(box t as Box + Send>), None => { - let wc: Option>> - = Terminal::new(box std::io::stdout() as Box); - wc.map(|w| box w as Box + Send> + Send>) + let wc: Option> + = Terminal::new(WriterWrapper { + wrapped: box std::io::stdout() as Box, + }); + wc.map(|w| box w as Box + Send>) } } } @@ -95,25 +119,31 @@ pub fn stdout() -> Option + Send> + Send>> { #[cfg(not(windows))] /// Return a Terminal wrapping stderr, or None if a terminal couldn't be /// opened. -pub fn stderr() -> Option + Send> + Send> + Send> { - let ti: Option>> - = Terminal::new(box std::io::stderr() as Box); - ti.map(|t| box t as Box + Send> + Send>) +pub fn stderr() -> Option + Send> + Send> { + let ti: Option> + = Terminal::new(WriterWrapper { + wrapped: box std::io::stderr() as Box, + }); + ti.map(|t| box t as Box + Send>) } #[cfg(windows)] /// Return a Terminal wrapping stderr, or None if a terminal couldn't be /// opened. -pub fn stderr() -> Option + Send> + Send>> { - let ti: Option>> - = Terminal::new(box std::io::stderr() as Box); +pub fn stderr() -> Option + Send> + Send> { + let ti: Option> + = Terminal::new(WriterWrapper { + wrapped: box std::io::stderr() as Box, + }); match ti { - Some(t) => Some(box t as Box + Send> + Send>), + Some(t) => Some(box t as Box + Send>), None => { - let wc: Option>> - = Terminal::new(box std::io::stderr() as Box); - wc.map(|w| box w as Box + Send> + Send>) + let wc: Option> + = Terminal::new(WriterWrapper { + wrapped: box std::io::stderr() as Box, + }); + wc.map(|w| box w as Box + Send>) } } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 589f605f8d234..26c9aaed568af 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -474,7 +474,7 @@ pub enum TestResult { } enum OutputLocation { - Pretty(Box> + Send>), + Pretty(Box + Send>), Raw(T), } diff --git a/src/test/compile-fail/regions-escape-via-trait-or-not.rs b/src/test/compile-fail/regions-escape-via-trait-or-not.rs index 7f54fe298a15e..980a4aed34f9e 100644 --- a/src/test/compile-fail/regions-escape-via-trait-or-not.rs +++ b/src/test/compile-fail/regions-escape-via-trait-or-not.rs @@ -23,7 +23,7 @@ fn with(f: |x: &int| -> R) -> int { } fn return_it() -> int { - with(|o| o) //~ ERROR lifetime of function argument does not outlive the function call + with(|o| o) //~ ERROR cannot infer an appropriate lifetime } fn main() { diff --git a/src/test/compile-fail/variance-trait-matching-2.rs b/src/test/compile-fail/variance-trait-matching-2.rs new file mode 100644 index 0000000000000..f549c78be9d0d --- /dev/null +++ b/src/test/compile-fail/variance-trait-matching-2.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +extern crate serialize; + +use std::io::MemWriter; +use std::io; +use serialize::{Encodable, Encoder}; + +pub fn buffer_encode<'a, + T:Encodable,io::IoError>>( + to_encode_object: &T) + -> Vec { + let mut m = MemWriter::new(); + { + let mut encoder = + serialize::json::Encoder::new(&mut m as &mut io::Writer); + //~^ ERROR `m` does not live long enough + to_encode_object.encode(&mut encoder); + } + m.unwrap() +} + +fn main() {} diff --git a/src/test/compile-fail/variance-trait-matching.rs b/src/test/compile-fail/variance-trait-matching.rs new file mode 100644 index 0000000000000..1644705222f70 --- /dev/null +++ b/src/test/compile-fail/variance-trait-matching.rs @@ -0,0 +1,30 @@ +// Copyright 2014 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. + +// Issue #5781. Tests that subtyping is handled properly in trait matching. + +trait Make<'a> { + fn make(x: &'a mut int) -> Self; +} + +impl<'a> Make<'a> for &'a mut int { + fn make(x: &'a mut int) -> &'a mut int { + x + } +} + +fn f() -> &'static mut int { + let mut x = 1; + let y: &'static mut int = Make::make(&mut x); //~ ERROR `x` does not live long enough + y +} + +fn main() {} + diff --git a/src/test/run-fail/fail-task-name-none.rs b/src/test/run-fail/fail-task-name-none.rs index 3f662e6d0e3e4..75d23d0f4fdf2 100644 --- a/src/test/run-fail/fail-task-name-none.rs +++ b/src/test/run-fail/fail-task-name-none.rs @@ -13,8 +13,9 @@ use std::task; fn main() { - task::try(proc() { + let r: Result = task::try(proc() { fail!("test"); - 1 - }).unwrap() + 1i + }); + assert!(r.is_ok()); } diff --git a/src/test/run-fail/fail-task-name-owned.rs b/src/test/run-fail/fail-task-name-owned.rs index ea643fd26d93d..b1c8963e684d6 100644 --- a/src/test/run-fail/fail-task-name-owned.rs +++ b/src/test/run-fail/fail-task-name-owned.rs @@ -13,8 +13,10 @@ use std::task::TaskBuilder; fn main() { - TaskBuilder::new().named("owned name".to_string()).try(proc() { + let r: Result = TaskBuilder::new().named("owned name".to_string()) + .try(proc() { fail!("test"); 1 - }).unwrap() + }); + assert!(r.is_ok()); } diff --git a/src/test/run-fail/fail-task-name-send-str.rs b/src/test/run-fail/fail-task-name-send-str.rs index d99c805323f3e..5153c5f2807b0 100644 --- a/src/test/run-fail/fail-task-name-send-str.rs +++ b/src/test/run-fail/fail-task-name-send-str.rs @@ -11,8 +11,11 @@ // error-pattern:task 'send name' failed at 'test' fn main() { - ::std::task::TaskBuilder::new().named("send name".into_maybe_owned()).try(proc() { - fail!("test"); - 3 - }).unwrap() + let r: Result = + ::std::task::TaskBuilder::new().named("send name".into_maybe_owned()) + .try(proc() { + fail!("test"); + 3 + }); + assert!(r.is_ok()); } diff --git a/src/test/run-fail/fail-task-name-static.rs b/src/test/run-fail/fail-task-name-static.rs index e0c98c5744e6a..0b2901889cbf2 100644 --- a/src/test/run-fail/fail-task-name-static.rs +++ b/src/test/run-fail/fail-task-name-static.rs @@ -11,7 +11,9 @@ // error-pattern:task 'static name' failed at 'test' fn main() { - ::std::task::TaskBuilder::new().named("static name").try(proc() { - fail!("test"); - }).unwrap() + let r: Result = + ::std::task::TaskBuilder::new().named("static name").try(proc() { + fail!("test"); + }); + assert!(r.is_ok()); } diff --git a/src/test/run-fail/task-spawn-barefn.rs b/src/test/run-fail/task-spawn-barefn.rs index ae189889967f7..e7fd97f8d31f3 100644 --- a/src/test/run-fail/task-spawn-barefn.rs +++ b/src/test/run-fail/task-spawn-barefn.rs @@ -15,7 +15,10 @@ use std::task; fn main() { // the purpose of this test is to make sure that task::spawn() // works when provided with a bare function: - task::try(startfn).unwrap(); + let r = task::try(startfn); + if r.is_err() { + fail!() + } } fn startfn() { diff --git a/src/test/run-pass/trait-contravariant-self.rs b/src/test/run-pass/trait-contravariant-self.rs index d8df5d5600c90..e06e01b9e0512 100644 --- a/src/test/run-pass/trait-contravariant-self.rs +++ b/src/test/run-pass/trait-contravariant-self.rs @@ -1,3 +1,5 @@ +// ignore-test + // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT.