about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-10-02 09:11:34 +0000
committerbors <bors@rust-lang.org>2015-10-02 09:11:34 +0000
commit70076ec8b22cba7689c76afef7085cb6917793ef (patch)
treebeb4dc6391a90dfbe6ad45b033d364fca311e40f
parenta004ff5cafb6111bcb3a00d67133a84ff727bad1 (diff)
parente4797fa22185f9ca52734ab4092754dd5963b3da (diff)
downloadrust-70076ec8b22cba7689c76afef7085cb6917793ef.tar.gz
rust-70076ec8b22cba7689c76afef7085cb6917793ef.zip
Auto merge of #28807 - Manishearth:rollup, r=Manishearth
- Successful merges: #28554, #28686, #28786, #28788, #28791, #28797
- Failed merges: 
-rw-r--r--src/doc/trpl/bibliography.md7
-rw-r--r--src/libcollections/vec.rs75
-rw-r--r--src/librustc/middle/const_eval.rs19
-rw-r--r--src/librustc_resolve/diagnostics.rs24
-rw-r--r--src/libstd/ffi/c_str.rs6
-rw-r--r--src/test/compile-fail/invalid-path-in-const.rs14
-rw-r--r--src/test/run-pass/issue-25439.rs19
7 files changed, 155 insertions, 9 deletions
diff --git a/src/doc/trpl/bibliography.md b/src/doc/trpl/bibliography.md
index 9659fe45857..b3c75df550f 100644
--- a/src/doc/trpl/bibliography.md
+++ b/src/doc/trpl/bibliography.md
@@ -61,8 +61,9 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
   Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex
   Light.
 * [Evaluation of performance and productivity metrics of potential
-  programming languages in the HPC environment](). Bachelor's thesis by
-  Florian Wilkens. Compares C, Go and Rust.
+  programming languages in the HPC environment]
+  (http://octarineparrot.com/assets/mrfloya-thesis-ba.pdf).
+  Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust.
 * [Nom, a byte oriented, streaming, zero copy, parser combinators library
   in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By
   Geoffroy Couprie, research for VLC.
@@ -77,4 +78,4 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
   Farnstrand's master's thesis.
 * [Session Types for
   Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
-  Munksgaard's master's thesis. Research for Servo.
\ No newline at end of file
+  Munksgaard's master's thesis. Research for Servo.
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index f2ede5c44d3..bcde523307c 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -148,6 +148,81 @@ use super::range::RangeArgument;
 /// if the vector's length is increased to 11, it will have to reallocate, which
 /// can be slow. For this reason, it is recommended to use `Vec::with_capacity`
 /// whenever possible to specify how big the vector is expected to get.
+///
+/// # Guarantees
+///
+/// Due to its incredibly fundamental nature, Vec makes a lot of guarantees
+/// about its design. This ensures that it's as low-overhead as possible in
+/// the general case, and can be correctly manipulated in primitive ways
+/// by unsafe code. Note that these guarantees refer to an unqualified `Vec<T>`.
+/// If additional type parameters are added (e.g. to support custom allocators),
+/// overriding their defaults may change the behavior.
+///
+/// Most fundamentally, Vec is and always will be a (pointer, capacity, length)
+/// triplet. No more, no less. The order of these fields is completely
+/// unspecified, and you should use the appropriate methods to modify these.
+/// The pointer will never be null, so this type is null-pointer-optimized.
+///
+/// However, the pointer may not actually point to allocated memory. In particular,
+/// if you construct a Vec with capacity 0 via `Vec::new()`, `vec![]`,
+/// `Vec::with_capacity(0)`, or by calling `shrink_to_fit()` on an empty Vec, it
+/// will not allocate memory. Similarly, if you store zero-sized types inside
+/// a Vec, it will not allocate space for them. *Note that in this case the
+/// Vec may not report a `capacity()` of 0*. Vec will allocate if and only
+/// if `mem::size_of::<T>() * capacity() > 0`. In general, Vec's allocation
+/// details are subtle enough that it is strongly recommended that you only
+/// free memory allocated by a Vec by creating a new Vec and dropping it.
+///
+/// If a Vec *has* allocated memory, then the memory it points to is on the heap
+/// (as defined by the allocator Rust is configured to use by default), and its
+/// pointer points to `len()` initialized elements in order (what you would see
+/// if you coerced it to a slice), followed by `capacity() - len()` logically
+/// uninitialized elements.
+///
+/// Vec will never perform a "small optimization" where elements are actually
+/// stored on the stack for two reasons:
+///
+/// * It would make it more difficult for unsafe code to correctly manipulate
+///   a Vec. The contents of a Vec wouldn't have a stable address if it were
+///   only moved, and it would be more difficult to determine if a Vec had
+///   actually allocated memory.
+///
+/// * It would penalize the general case, incurring an additional branch
+///   on every access.
+///
+/// Vec will never automatically shrink itself, even if completely empty. This
+/// ensures no unnecessary allocations or deallocations occur. Emptying a Vec
+/// and then filling it back up to the same `len()` should incur no calls to
+/// the allocator. If you wish to free up unused memory, use `shrink_to_fit`.
+///
+/// `push` and `insert` will never (re)allocate if the reported capacity is
+/// sufficient. `push` and `insert` *will* (re)allocate if `len() == capacity()`.
+/// That is, the reported capacity is completely accurate, and can be relied on.
+/// It can even be used to manually free the memory allocated by a Vec if
+/// desired. Bulk insertion methods *may* reallocate, even when not necessary.
+///
+/// Vec does not guarantee any particular growth strategy when reallocating
+/// when full, nor when `reserve` is called. The current strategy is basic
+/// and it may prove desirable to use a non-constant growth factor. Whatever
+/// strategy is used will of course guarantee `O(1)` amortized `push`.
+///
+/// `vec![x; n]`, `vec![a, b, c, d]`, and `Vec::with_capacity(n)`, will all
+/// produce a Vec with exactly the requested capacity. If `len() == capacity()`,
+/// (as is the case for the `vec!` macro), then a `Vec<T>` can be converted
+/// to and from a `Box<[T]>` without reallocating or moving the elements.
+///
+/// Vec will not specifically overwrite any data that is removed from it,
+/// but also won't specifically preserve it. Its uninitialized memory is
+/// scratch space that it may use however it wants. It will generally just do
+/// whatever is most efficient or otherwise easy to implement. Do not rely on
+/// removed data to be erased for security purposes. Even if you drop a Vec, its
+/// buffer may simply be reused by another Vec. Even if you zero a Vec's memory
+/// first, that may not actually happen because the optimizer does not consider
+/// this a side-effect that must be preserved.
+///
+/// Vec does not currently guarantee the order in which elements are dropped
+/// (the order has changed in the past, and may change again).
+///
 #[unsafe_no_drop_flag]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Vec<T> {
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 2d74525e4ed..d3f427e770c 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -367,6 +367,7 @@ pub enum ErrKind {
     ShiftRightWithOverflow,
     MissingStructField,
     NonConstPath,
+    UnresolvedPath,
     ExpectedConstTuple,
     ExpectedConstStruct,
     TupleIndexOutOfBounds,
@@ -403,7 +404,8 @@ impl ConstEvalErr {
             ShiftLeftWithOverflow => "attempted left shift with overflow".into_cow(),
             ShiftRightWithOverflow => "attempted right shift with overflow".into_cow(),
             MissingStructField  => "nonexistent struct field".into_cow(),
-            NonConstPath        => "non-constant path in constant expr".into_cow(),
+            NonConstPath        => "non-constant path in constant expression".into_cow(),
+            UnresolvedPath => "unresolved path in constant expression".into_cow(),
             ExpectedConstTuple => "expected constant tuple".into_cow(),
             ExpectedConstStruct => "expected constant struct".into_cow(),
             TupleIndexOutOfBounds => "tuple index out of bounds".into_cow(),
@@ -895,7 +897,20 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
         }
       }
       hir::ExprPath(..) => {
-          let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
+          let opt_def = if let Some(def) = tcx.def_map.borrow().get(&e.id) {
+              // After type-checking, def_map contains definition of the
+              // item referred to by the path. During type-checking, it
+              // can contain the raw output of path resolution, which
+              // might be a partially resolved path.
+              // FIXME: There's probably a better way to make sure we don't
+              // panic here.
+              if def.depth != 0 {
+                  signal!(e, UnresolvedPath);
+              }
+              Some(def.full_def())
+          } else {
+              None
+          };
           let (const_expr, const_ty) = match opt_def {
               Some(def::DefConst(def_id)) => {
                   if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index f06fd9f70e2..4147f2bea48 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -609,6 +609,29 @@ match Something::NotFoo {
 ```
 "##,
 
+E0422: r##"
+You are trying to use an identifier that is either undefined or not a
+struct. For instance:
+```
+fn main () {
+    let x = Foo { x: 1, y: 2 };
+}
+```
+
+In this case, `Foo` is undefined, so it inherently isn't anything, and
+definitely not a struct.
+
+```
+fn main () {
+    let foo = 1;
+    let x = foo { x: 1, y: 2 };
+}
+```
+
+In this case, `foo` is defined, but is not a struct, so Rust can't use
+it as one.
+"##,
+
 E0423: r##"
 A `struct` variant name was used like a function name. Example of
 erroneous code:
@@ -888,7 +911,6 @@ register_diagnostics! {
     E0418, // is not an enum variant, struct or const
     E0420, // is not an associated const
     E0421, // unresolved associated const
-    E0422, // does not name a structure
     E0427, // cannot use `ref` binding mode with ...
     E0429, // `self` imports are only allowed within a { } list
     E0434, // can't capture dynamic environment in a fn item
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 7c9c2066ae9..6b7ecaa77d1 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -206,7 +206,7 @@ impl CString {
     /// Retakes ownership of a CString that was transferred to C.
     ///
     /// The only appropriate argument is a pointer obtained by calling
-    /// `into_ptr`. The length of the string will be recalculated
+    /// `into_raw`. The length of the string will be recalculated
     /// using the pointer.
     #[unstable(feature = "cstr_memory2", reason = "recently added",
                issue = "27769")]
@@ -245,11 +245,11 @@ impl CString {
     /// Transfers ownership of the string to a C caller.
     ///
     /// The pointer must be returned to Rust and reconstituted using
-    /// `from_ptr` to be properly deallocated. Specifically, one
+    /// `from_raw` to be properly deallocated. Specifically, one
     /// should *not* use the standard C `free` function to deallocate
     /// this string.
     ///
-    /// Failure to call `from_ptr` will lead to a memory leak.
+    /// Failure to call `from_raw` will lead to a memory leak.
     #[stable(feature = "cstr_memory", since = "1.4.0")]
     pub fn into_raw(self) -> *mut libc::c_char {
         Box::into_raw(self.inner) as *mut libc::c_char
diff --git a/src/test/compile-fail/invalid-path-in-const.rs b/src/test/compile-fail/invalid-path-in-const.rs
new file mode 100644
index 00000000000..3c4ad5a56ec
--- /dev/null
+++ b/src/test/compile-fail/invalid-path-in-const.rs
@@ -0,0 +1,14 @@
+// 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.
+
+fn main() {
+    fn f(a: [u8; u32::DOESNOTEXIST]) {}
+    //~^ ERROR unresolved path in constant expression
+}
diff --git a/src/test/run-pass/issue-25439.rs b/src/test/run-pass/issue-25439.rs
new file mode 100644
index 00000000000..88c48f42c51
--- /dev/null
+++ b/src/test/run-pass/issue-25439.rs
@@ -0,0 +1,19 @@
+// 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.
+
+struct Helper<'a, F: 'a>(&'a F);
+
+fn fix<F>(f: F) -> i32 where F: Fn(Helper<F>, i32) -> i32 {
+    f(Helper(&f), 8)
+}
+
+fn main() {
+    fix(|_, x| x);
+}