From a818f9f6b63eca633e51612a2674d3e69acb3294 Mon Sep 17 00:00:00 2001 From: christopherdumas Date: Sun, 20 Sep 2015 13:36:08 -0700 Subject: [PATCH 1/8] E0422 description. --- src/librustc_resolve/diagnostics.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index f06fd9f70e2c1..4147f2bea4850 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 From 1763fcb36d85767fa1fee4c2de66fc2855633fcd Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 30 Sep 2015 15:04:21 -0700 Subject: [PATCH 2/8] Don't crash on non-existent path in constant. The behavior here isn't really ideal, but we can't really do much better given the current state of constant evaluation. Fixes #28670, and probably a bunch of duplicates. --- src/librustc/middle/const_eval.rs | 19 +++++++++++++++++-- .../compile-fail/invalid-path-in-const.rs | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/invalid-path-in-const.rs diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 4894a78f1acb4..50e74d196e674 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -388,6 +388,7 @@ pub enum ErrKind { ShiftRightWithOverflow, MissingStructField, NonConstPath, + UnresolvedPath, ExpectedConstTuple, ExpectedConstStruct, TupleIndexOutOfBounds, @@ -424,7 +425,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(), @@ -916,7 +918,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 def_id.is_local() { 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 0000000000000..3c4ad5a56ec36 --- /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 or the MIT license +// , 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 +} From d76010f3d9453c679bd544afb655d1f3b3c15817 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 1 Oct 2015 11:36:26 +0200 Subject: [PATCH 3/8] Add link to Florian Wilkens's Bachelor's Thesis --- src/doc/trpl/bibliography.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/doc/trpl/bibliography.md b/src/doc/trpl/bibliography.md index 9659fe45857f9..b3c75df550f7f 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. From 566dc9cf9377457e4d099d3306c30014ad582963 Mon Sep 17 00:00:00 2001 From: Cristian Kubis Date: Thu, 1 Oct 2015 12:43:00 +0200 Subject: [PATCH 4/8] doc: fixed swapped docs for from_ptr and from_raw --- src/libstd/ffi/c_str.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 7c9c2066ae93a..70e9eca31e56b 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -230,11 +230,11 @@ impl CString { /// Transfers ownership of the string to a C caller. /// /// The pointer must be returned to Rust and reconstituted using - /// `from_raw` to be properly deallocated. Specifically, one + /// `from_ptr` to be properly deallocated. Specifically, one /// should *not* use the standard C `free` function to deallocate /// this string. /// - /// Failure to call `from_raw` will lead to a memory leak. + /// Failure to call `from_ptr` will lead to a memory leak. #[unstable(feature = "cstr_memory2", reason = "recently added", issue = "27769")] #[deprecated(since = "1.4.0", reason = "renamed to into_raw")] @@ -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 From 25c21342c62cf92d709ea3df493cfbb3718e5d0c Mon Sep 17 00:00:00 2001 From: Cristian Kubis Date: Thu, 1 Oct 2015 16:02:35 +0200 Subject: [PATCH 5/8] replaced *_ptr with *_raw methods in docs --- src/libstd/ffi/c_str.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 70e9eca31e56b..6b7ecaa77d10f 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")] @@ -230,11 +230,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. #[unstable(feature = "cstr_memory2", reason = "recently added", issue = "27769")] #[deprecated(since = "1.4.0", reason = "renamed to into_raw")] From a81dfca190e1b8556f8c94db1d5856840645c1f9 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Thu, 1 Oct 2015 11:25:45 -0400 Subject: [PATCH 6/8] Add test for #25439 Closes #25439. --- src/test/run-pass/issue-25439.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/run-pass/issue-25439.rs diff --git a/src/test/run-pass/issue-25439.rs b/src/test/run-pass/issue-25439.rs new file mode 100644 index 0000000000000..88c48f42c513c --- /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 or the MIT license +// , 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) -> i32 where F: Fn(Helper, i32) -> i32 { + f(Helper(&f), 8) +} + +fn main() { + fix(|_, x| x); +} From 9ef2651dff3bdee3fd91d474a15dea9a4b5ece08 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 19 Aug 2015 10:13:39 -0700 Subject: [PATCH 7/8] flesh out what Vec actually guarantees --- src/libcollections/vec.rs | 75 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index f2ede5c44d312..ee44fb0541ec1 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`. +/// 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::() * 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 unnecessarily. +/// +/// 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` 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 { From c7527a199953d4f902241279fb457c86c80f5927 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 19 Aug 2015 12:36:14 -0700 Subject: [PATCH 8/8] fixup wording --- src/libcollections/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index ee44fb0541ec1..bcde523307c83 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -199,7 +199,7 @@ use super::range::RangeArgument; /// 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 unnecessarily. +/// 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