* Language
* The `for` loop syntax has changed to work with the `Iterator` trait.
* At long last, unwinding works on Windows.
- * Default methods definitely mostly work.
+ * Default methods are ready for use.
* Many trait inheritance bugs fixed.
* Owned and borrowed trait objects work more reliably.
* `copy` is no longer a keyword. It has been replaced by the `Clone` trait.
be specified with `#[link_section = "..."]`.
* The `proto!` syntax extension for defining bounded message protocols
was removed.
- * `macro_rules!` is hygenic for `let` declarations.
+ * `macro_rules!` is hygienic for `let` declarations.
* The `#[export_name]` attribute specifies the name of a symbol.
* `unreachable!` can be used to indicate unreachable code, and fails
if executed.
* std: Added `SharedPort` to `comm`.
* std: `Eq` has a default method for `ne`; only `eq` is required
in implementations.
- * std: `Ord` has default methods for `le`, `gt` and `le`; only `lt`
+ * std: `Ord` has default methods for `le`, `gt` and `ge`; only `lt`
is required in implementations.
* std: `is_utf8` performance is improved, impacting many string functions.
* std: `os::MemoryMap` provides cross-platform mmap.
* rustc's debug info generation (`-Z debug-info`) is greatly improved.
* rustc accepts `--target-cpu` to compile to a specific CPU architecture,
similarly to gcc's `--march` flag.
+ * rustc's performance compiling small crates is much better.
* rustpkg has received many improvements.
* rustpkg supports git tags as package IDs.
* rustpkg builds into target-specific directories so it can be used for
use util::ppaux;
use util::ppaux::Repr;
use util::common::indenter;
+use util::ppaux::UserString;
use std::at_vec;
use std::hashmap::{HashSet, HashMap};
ty::type_moves_by_default(self.tcx, tf.mt.ty)
});
+ fn has_dtor(tcx: ty::ctxt, ty: ty::t) -> bool {
+ use middle::ty::{get,ty_struct,ty_enum};
+ match get(ty).sty {
+ ty_struct(did, _) | ty_enum(did, _) => ty::has_dtor(tcx, did),
+ _ => false,
+ }
+ }
+
if consume_with {
+ if has_dtor(self.tcx, with_ty) {
+ self.tcx.sess.span_err(with_expr.span,
+ fmt!("cannot move out of type `%s`, \
+ which defines the `Drop` trait",
+ with_ty.user_string(self.tcx)));
+ }
self.consume_expr(*with_expr, visitor);
} else {
self.use_expr(*with_expr, Read, visitor);
--- /dev/null
+// 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 <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.
+
+// Issue 4691: Ensure that functional-struct-update can only copy, not
+// move, when the struct implements Drop.
+
+use NC = std::util::NonCopyable;
+struct S { a: int, nc: NC }
+impl Drop for S { fn drop(&mut self) { } }
+
+struct T { a: int, mv: ~int }
+impl Drop for T { fn drop(&mut self) { } }
+
+fn f(s0:S) {
+ let _s2 = S{a: 2, ..s0}; //~error: cannot move out of type `S`, which defines the `Drop` trait
+}
+
+fn g(s0:T) {
+ let _s2 = T{a: 2, ..s0}; //~error: cannot move out of type `T`, which defines the `Drop` trait
+}
+
+fn main() { }
--- /dev/null
+// 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 <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.
+
+// Issue 4691: Ensure that functional-struct-updates operates
+// correctly and moves rather than copy when appropriate.
+
+use NC = std::util::NonCopyable;
+
+struct ncint { nc: NC, v: int }
+fn ncint(v: int) -> ncint { ncint { nc: NC, v: v } }
+
+struct NoFoo { copied: int, noncopy: ncint, }
+impl NoFoo {
+ fn new(x:int,y:int) -> NoFoo { NoFoo { copied: x, noncopy: ncint(y) } }
+}
+
+struct MoveFoo { copied: int, moved: ~int, }
+impl MoveFoo {
+ fn new(x:int,y:int) -> MoveFoo { MoveFoo { copied: x, moved: ~y } }
+}
+
+struct DropNoFoo { inner: NoFoo }
+impl DropNoFoo {
+ fn new(x:int,y:int) -> DropNoFoo { DropNoFoo { inner: NoFoo::new(x,y) } }
+}
+impl Drop for DropNoFoo { fn drop(&mut self) { } }
+
+struct DropMoveFoo { inner: MoveFoo }
+impl DropMoveFoo {
+ fn new(x:int,y:int) -> DropMoveFoo { DropMoveFoo { inner: MoveFoo::new(x,y) } }
+}
+impl Drop for DropMoveFoo { fn drop(&mut self) { } }
+
+
+fn test0() {
+ // just copy implicitly copyable fields from `f`, no moves
+ // (and thus it is okay that these are Drop; compare against
+ // compile-fail test: borrowck-struct-update-with-dtor.rs).
+
+ // Case 1: NonCopyable
+ let f = DropNoFoo::new(1, 2);
+ let b = DropNoFoo { inner: NoFoo { noncopy: ncint(3), ..f.inner }};
+ let c = DropNoFoo { inner: NoFoo { noncopy: ncint(4), ..f.inner }};
+ assert_eq!(f.inner.copied, 1);
+ assert_eq!(f.inner.noncopy.v, 2);
+
+ assert_eq!(b.inner.copied, 1);
+ assert_eq!(b.inner.noncopy.v, 3);
+
+ assert_eq!(c.inner.copied, 1);
+ assert_eq!(c.inner.noncopy.v, 4);
+
+ // Case 2: Owned
+ let f = DropMoveFoo::new(5, 6);
+ let b = DropMoveFoo { inner: MoveFoo { moved: ~7, ..f.inner }};
+ let c = DropMoveFoo { inner: MoveFoo { moved: ~8, ..f.inner }};
+ assert_eq!(f.inner.copied, 5);
+ assert_eq!(*f.inner.moved, 6);
+
+ assert_eq!(b.inner.copied, 5);
+ assert_eq!(*b.inner.moved, 7);
+
+ assert_eq!(c.inner.copied, 5);
+ assert_eq!(*c.inner.moved, 8);
+}
+
+fn test1() {
+ // copying move-by-default fields from `f`, so it moves:
+ let f = MoveFoo::new(11, 12);
+
+ let b = MoveFoo {moved: ~13, ..f};
+ let c = MoveFoo {copied: 14, ..f};
+ assert_eq!(b.copied, 11);
+ assert_eq!(*b.moved, 13);
+ assert_eq!(c.copied, 14);
+ assert_eq!(*c.moved, 12);
+}
+
+fn test2() {
+ // move non-copyable field
+ let f = NoFoo::new(21, 22);
+ let b = NoFoo {noncopy: ncint(23), ..f};
+ let c = NoFoo {copied: 24, ..f};
+ assert_eq!(b.copied, 21);
+ assert_eq!(b.noncopy.v, 23);
+ assert_eq!(c.copied, 24);
+ assert_eq!(c.noncopy.v, 22);
+}
+
+fn main() {
+ test0();
+ test1();
+ test2();
+}