From 419ac4a1b899ba88fb360b4c71c08f3610564cd4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 15 Jan 2014 14:39:08 -0500 Subject: Issue #3511 - Rationalize temporary lifetimes. Major changes: - Define temporary scopes in a syntax-based way that basically defaults to the innermost statement or conditional block, except for in a `let` initializer, where we default to the innermost block. Rules are documented in the code, but not in the manual (yet). See new test run-pass/cleanup-value-scopes.rs for examples. - Refactors Datum to better define cleanup roles. - Refactor cleanup scopes to not be tied to basic blocks, permitting us to have a very large number of scopes (one per AST node). - Introduce nascent documentation in trans/doc.rs covering datums and cleanup in a more comprehensive way. --- src/libstd/ascii.rs | 13 +++++++++---- src/libstd/io/mem.rs | 6 ++++-- src/libstd/io/process.rs | 14 +++++++------- src/libstd/option.rs | 19 +++++++++++++++++++ src/libstd/path/posix.rs | 13 ++++++++++--- src/libstd/path/windows.rs | 14 ++++++++++---- src/libstd/rt/crate_map.rs | 18 +++++++++--------- src/libstd/unstable/intrinsics.rs | 6 ------ src/libstd/util.rs | 2 +- src/libstd/vec.rs | 31 ++++++++++++++++++++++++++++++- 10 files changed, 99 insertions(+), 37 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index c52ff2d088d..546f5550387 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -521,7 +521,8 @@ mod tests { #[test] fn test_ascii_vec() { - assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59])); + let test = &[40u8, 32u8, 59u8]; + assert_eq!(test.to_ascii(), v2ascii!([40, 32, 59])); assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59])); // FIXME: #5475 borrowchk error, owned vectors do not live long enough // if chained-from directly @@ -587,14 +588,18 @@ mod tests { assert_eq!("zoä华".to_ascii_opt(), None); - assert_eq!((&[127u8, 128u8, 255u8]).to_ascii_opt(), None); + let test1 = &[127u8, 128u8, 255u8]; + assert_eq!((test1).to_ascii_opt(), None); let v = [40u8, 32u8, 59u8]; - assert_eq!(v.to_ascii_opt(), Some(v2ascii!(&[40, 32, 59]))); + let v2 = v2ascii!(&[40, 32, 59]); + assert_eq!(v.to_ascii_opt(), Some(v2)); let v = [127u8, 128u8, 255u8]; assert_eq!(v.to_ascii_opt(), None); - assert_eq!("( ;".to_ascii_opt(), Some(v2ascii!(&[40, 32, 59]))); + let v = "( ;"; + let v2 = v2ascii!(&[40, 32, 59]); + assert_eq!(v.to_ascii_opt(), Some(v2)); assert_eq!("zoä华".to_ascii_opt(), None); assert_eq!((~[40u8, 32u8, 59u8]).into_ascii_opt(), Some(v2ascii!(~[40, 32, 59]))); diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index f036131d211..a6caa1bfc29 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -406,7 +406,8 @@ mod test { #[test] fn test_read_char() { - let mut r = BufReader::new(bytes!("Việt")); + let b = bytes!("Việt"); + let mut r = BufReader::new(b); assert_eq!(r.read_char(), Some('V')); assert_eq!(r.read_char(), Some('i')); assert_eq!(r.read_char(), Some('ệ')); @@ -416,7 +417,8 @@ mod test { #[test] fn test_read_bad_char() { - let mut r = BufReader::new(bytes!(0x80)); + let b = bytes!(0x80); + let mut r = BufReader::new(b); assert_eq!(r.read_char(), None); } diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index a8b7e8e00ea..4c8a640a849 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -181,7 +181,7 @@ mod tests { let io = ~[]; let args = ProcessConfig { program: "/bin/sh", - args: [~"-c", ~"true"], + args: &[~"-c", ~"true"], env: None, cwd: None, io: io, @@ -198,7 +198,7 @@ mod tests { let io = ~[]; let args = ProcessConfig { program: "if-this-is-a-binary-then-the-world-has-ended", - args: [], + args: &[], env: None, cwd: None, io: io, @@ -215,7 +215,7 @@ mod tests { let io = ~[]; let args = ProcessConfig { program: "/bin/sh", - args: [~"-c", ~"exit 1"], + args: &[~"-c", ~"exit 1"], env: None, cwd: None, io: io, @@ -231,7 +231,7 @@ mod tests { let io = ~[]; let args = ProcessConfig { program: "/bin/sh", - args: [~"-c", ~"kill -1 $$"], + args: &[~"-c", ~"kill -1 $$"], env: None, cwd: None, io: io, @@ -274,7 +274,7 @@ mod tests { let io = ~[Ignored, CreatePipe(false, true)]; let args = ProcessConfig { program: "/bin/sh", - args: [~"-c", ~"echo foobar"], + args: &[~"-c", ~"echo foobar"], env: None, cwd: None, io: io, @@ -289,7 +289,7 @@ mod tests { let cwd = Some("/"); let args = ProcessConfig { program: "/bin/sh", - args: [~"-c", ~"pwd"], + args: &[~"-c", ~"pwd"], env: None, cwd: cwd, io: io, @@ -304,7 +304,7 @@ mod tests { CreatePipe(false, true)]; let args = ProcessConfig { program: "/bin/sh", - args: [~"-c", ~"read line; echo $line"], + args: &[~"-c", ~"read line; echo $line"], env: None, cwd: None, io: io, diff --git a/src/libstd/option.rs b/src/libstd/option.rs index bdec67e5d9f..aab98f19e15 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -48,6 +48,7 @@ use kinds::Send; use str::OwnedStr; use to_str::ToStr; use util; +use vec; /// The option type #[deriving(Clone, DeepClone, Eq, Ord, TotalEq, TotalOrd, ToStr)] @@ -98,6 +99,24 @@ impl Option { match *self { Some(ref mut x) => Some(x), None => None } } + /// Convert from `Option` to `&[T]` (without copying) + #[inline] + pub fn as_slice<'r>(&'r self) -> &'r [T] { + match *self { + Some(ref x) => vec::ref_slice(x), + None => &[] + } + } + + /// Convert from `Option` to `&[T]` (without copying) + #[inline] + pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] { + match *self { + Some(ref mut x) => vec::mut_ref_slice(x), + None => &mut [] + } + } + ///////////////////////////////////////////////////////////////////////// // Getting to contained values ///////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 7b94de6c094..e2ddabc1714 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -237,7 +237,10 @@ impl GenericPath for Path { let mut ita = self.components(); let mut itb = other.components(); if bytes!(".") == self.repr { - return itb.next() != Some(bytes!("..")); + return match itb.next() { + None => true, + Some(b) => b != bytes!("..") + }; } loop { match (ita.next(), itb.next()) { @@ -463,7 +466,10 @@ mod tests { macro_rules! b( ($($arg:expr),+) => ( - bytes!($($arg),+) + { + static the_bytes: &'static [u8] = bytes!($($arg),+); + the_bytes + } ) ) @@ -689,7 +695,8 @@ mod tests { ); (v: $path:expr, $op:ident, $exp:expr) => ( { - let path = Path::new($path); + let arg = $path; + let path = Path::new(arg); assert_eq!(path.$op(), $exp); } ); diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 09b00be7e9d..cf2163265e4 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1074,7 +1074,10 @@ mod tests { macro_rules! b( ($($arg:expr),+) => ( - bytes!($($arg),+) + { + static the_bytes: &'static [u8] = bytes!($($arg),+); + the_bytes + } ) ) @@ -1372,20 +1375,23 @@ mod tests { macro_rules! t( (s: $path:expr, $op:ident, $exp:expr) => ( { - let path = Path::new($path); + let path = $path; + let path = Path::new(path); assert_eq!(path.$op(), Some($exp)); } ); (s: $path:expr, $op:ident, $exp:expr, opt) => ( { - let path = Path::new($path); + let path = $path; + let path = Path::new(path); let left = path.$op(); assert_eq!(left, $exp); } ); (v: $path:expr, $op:ident, $exp:expr) => ( { - let path = Path::new($path); + let path = $path; + let path = Path::new(path); assert_eq!(path.$op(), $exp); } ) diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index 16c1ad25448..6ea12659e77 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -130,14 +130,14 @@ mod tests { let child_crate = CrateMap { version: 2, entries: entries, - children: [], + children: &[], event_loop_factory: None, }; let root_crate = CrateMap { version: 2, - entries: [], - children: [&child_crate, &child_crate], + entries: &[], + children: &[&child_crate, &child_crate], event_loop_factory: None, }; @@ -157,29 +157,29 @@ mod tests { let mut level3: u32 = 3; let child_crate2 = CrateMap { version: 2, - entries: [ + entries: &[ ModEntry { name: "c::m1", log_level: &mut level2}, ModEntry { name: "c::m2", log_level: &mut level3}, ], - children: [], + children: &[], event_loop_factory: None, }; let child_crate1 = CrateMap { version: 2, - entries: [ + entries: &[ ModEntry { name: "t::f1", log_level: &mut 1}, ], - children: [&child_crate2], + children: &[&child_crate2], event_loop_factory: None, }; let root_crate = CrateMap { version: 2, - entries: [ + entries: &[ ModEntry { name: "t::f2", log_level: &mut 0}, ], - children: [&child_crate1], + children: &[&child_crate1], event_loop_factory: None, }; diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 18a1790cd9b..63c0d628ce2 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -329,12 +329,6 @@ extern "rust-intrinsic" { /// elements. pub fn size_of() -> uint; - /// Move a value to a memory location containing a value. - /// - /// Drop glue is run on the destination, which must contain a - /// valid Rust value. - pub fn move_val(dst: &mut T, src: T); - /// Move a value to an uninitialized memory location. /// /// Drop glue is not run on the destination. diff --git a/src/libstd/util.rs b/src/libstd/util.rs index 06c7923bfed..22b07d6548f 100644 --- a/src/libstd/util.rs +++ b/src/libstd/util.rs @@ -134,7 +134,7 @@ mod tests { } } -/// Completely miscellaneous language-construct benchmarks. +/// Completely miscellaneous language-constracuct benchmarks. #[cfg(test)] mod bench { diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 797582e57f4..fd7640de126 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -168,7 +168,7 @@ pub fn from_elem(n_elts: uint, t: T) -> ~[T] { let mut v = with_capacity(n_elts); let p = v.as_mut_ptr(); let mut i = 0u; - (|| { + (|| { // FIXME what if we fail in the middle of this loop? while i < n_elts { intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i as int)), t.clone()); i += 1u; @@ -239,6 +239,25 @@ pub fn build(size: Option, builder: |push: |v: A||) -> ~[A] { vec } +/** + * Converts a pointer to A into a slice of length 1 (without copying). + */ +pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { + unsafe { + cast::transmute(Slice { data: s, len: 1 }) + } +} + +/** + * Converts a pointer to A into a slice of length 1 (without copying). + */ +pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { + unsafe { + let ptr: *A = cast::transmute(s); + cast::transmute(Slice { data: ptr, len: 1 }) + } +} + /// An iterator over the slices of a vector separated by elements that /// match a predicate function. pub struct SplitIterator<'a, T> { @@ -2175,6 +2194,9 @@ pub trait MutableVector<'a, T> { /// Returns an iterator that allows modifying each value fn mut_iter(self) -> VecMutIterator<'a, T>; + /// Returns a mutable pointer to the last item in the vector. + fn mut_last(self) -> &'a mut T; + /// Returns a reversed iterator that allows modifying each value fn mut_rev_iter(self) -> MutRevIterator<'a, T>; @@ -2437,6 +2459,13 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] { } } + #[inline] + fn mut_last(self) -> &'a mut T { + let len = self.len(); + if len == 0 { fail!("mut_last: empty vector") } + &mut self[len - 1] + } + #[inline] fn mut_rev_iter(self) -> MutRevIterator<'a, T> { self.mut_iter().invert() -- cgit 1.4.1-3-g733a5 From 6badef49fe502ca22aaabd4309bd899eea4144d4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 15 Jan 2014 19:44:38 -0500 Subject: Remove FIXMEs and add license --- src/librustc/middle/region.rs | 4 ++-- src/librustc/middle/trans/_match.rs | 2 -- src/librustc/middle/trans/doc.rs | 10 ++++++++++ src/libstd/vec.rs | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src/libstd') diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 3f4e5a4ef89..a224a90a6a4 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -615,7 +615,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, // A, but the inner rvalues `a()` and `b()` have an extended lifetime // due to rule C. // - // FIXME -- Note that `[]` patterns work more smoothly post-DST. + // FIXME(#6308) -- Note that `[]` patterns work more smoothly post-DST. match local.init { Some(expr) => { @@ -778,7 +778,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, ast::ExprField(ref subexpr, _, _) | ast::ExprIndex(_, ref subexpr, _) | ast::ExprParen(ref subexpr) => { - let subexpr: &'a @Expr = subexpr; // FIXME + let subexpr: &'a @Expr = subexpr; // FIXME(#11586) expr = &**subexpr; } _ => { diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index c7eb837aaf8..96367c769fd 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -2092,8 +2092,6 @@ fn bind_irrefutable_pat<'a>( * - pat: the irrefutable pattern being matched. * - val: the value being matched -- must be an lvalue (by ref, with cleanup) * - binding_mode: is this for an argument or a local variable? - * - * FIXME: convert `val` to `Datum` for more type safety */ debug!("bind_irrefutable_pat(bcx={}, pat={}, binding_mode={:?})", diff --git a/src/librustc/middle/trans/doc.rs b/src/librustc/middle/trans/doc.rs index c781d1dcbbf..b44f2ba2008 100644 --- a/src/librustc/middle/trans/doc.rs +++ b/src/librustc/middle/trans/doc.rs @@ -1,3 +1,13 @@ +// 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. + /*! # Documentation for the trans module diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index fd7640de126..1211882fd5d 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -168,7 +168,7 @@ pub fn from_elem(n_elts: uint, t: T) -> ~[T] { let mut v = with_capacity(n_elts); let p = v.as_mut_ptr(); let mut i = 0u; - (|| { // FIXME what if we fail in the middle of this loop? + (|| { while i < n_elts { intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i as int)), t.clone()); i += 1u; -- cgit 1.4.1-3-g733a5 From 7ff6b094fb5c0c7f58e08a9a7c25ff9ec5bbd643 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 16 Jan 2014 05:56:56 -0500 Subject: Remove typo --- src/libstd/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/util.rs b/src/libstd/util.rs index 22b07d6548f..06c7923bfed 100644 --- a/src/libstd/util.rs +++ b/src/libstd/util.rs @@ -134,7 +134,7 @@ mod tests { } } -/// Completely miscellaneous language-constracuct benchmarks. +/// Completely miscellaneous language-construct benchmarks. #[cfg(test)] mod bench { -- cgit 1.4.1-3-g733a5 From fd318300cf713f0e74f3a834f6c07970b85f17e4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 16 Jan 2014 18:47:22 -0500 Subject: Fix test to account for new temporary lifetime rules, which cause the channel to be dropped prematurely. --- src/libstd/comm/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index bf9e28f3e97..985a387ee2b 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -1202,7 +1202,7 @@ mod test { }) test!(fn oneshot_single_thread_peek_open() { - let (port, _) = Chan::::new(); + let (port, _chan) = Chan::::new(); assert_eq!(port.try_recv(), Empty); }) -- cgit 1.4.1-3-g733a5