diff --git a/configure b/configure index 3d8f0d863f5..9aa23e732ab 100755 --- a/configure +++ b/configure @@ -453,6 +453,8 @@ valopt datadir "${CFG_PREFIX}/share" "install data" valopt infodir "${CFG_PREFIX}/share/info" "install additional info" valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH" +valopt release-channel "source" "the name of the release channel to build" + # On windows we just store the libraries in the bin directory because # there's no rpath. This is where the build system itself puts libraries; # --libdir is used to configure the installation directory. @@ -481,6 +483,23 @@ CFG_BUILD=`echo "${CFG_BUILD}" | sed 's/-pc-mingw32/-w64-mingw32/g'` CFG_HOST=`echo "${CFG_HOST}" | sed 's/-pc-mingw32/-w64-mingw32/g'` CFG_TARGET=`echo "${CFG_TARGET}" | sed 's/-pc-mingw32/-w64-mingw32/g'` +# Validate the release channel +case "$CFG_RELEASE_CHANNEL" in + (source | nightly | beta | stable) + ;; + (*) + err "release channel must be 'source', 'nightly', 'beta' or 'stable'" + ;; +esac + +# Continue supporting the old --enable-nightly flag to transition the bots +# XXX Remove me +if [ $CFG_ENABLE_NIGHTLY -eq 1 ] +then + CFG_RELEASE_CHANNEL=nightly + putvar CFG_RELEASE_CHANNEL +fi + step_msg "looking for build programs" probe_need CFG_PERL perl @@ -636,7 +655,7 @@ then # check that gcc, cc and g++ all point to the same compiler. # note that for xcode 5, g++ points to clang, not clang++ if !((chk_cc gcc clang && chk_cc g++ clang) || - (chk_cc gcc gcc &&( chk_cc g++ g++ || chk g++ gcc))) then + (chk_cc gcc gcc &&( chk_cc g++ g++ || chk g++ gcc))); then err "the gcc and g++ in your path point to different compilers. Check which versions are in your path with gcc --version and g++ --version. To resolve this problem, either fix your PATH or run configure with --enable-clang" diff --git a/man/rustc.1 b/man/rustc.1 index 00d698e611e..6b7243541c4 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -1,4 +1,4 @@ -.TH RUSTC "1" "March 2014" "rustc 0.12.0-pre" "User Commands" +.TH RUSTC "1" "March 2014" "rustc 0.12.0" "User Commands" .SH NAME rustc \- The Rust compiler .SH SYNOPSIS diff --git a/man/rustdoc.1 b/man/rustdoc.1 index 12e776b9861..e675aca38aa 100644 --- a/man/rustdoc.1 +++ b/man/rustdoc.1 @@ -1,4 +1,4 @@ -.TH RUSTDOC "1" "March 2014" "rustdoc 0.12.0-pre" "User Commands" +.TH RUSTDOC "1" "March 2014" "rustdoc 0.12.0" "User Commands" .SH NAME rustdoc \- generate documentation from Rust source code .SH SYNOPSIS diff --git a/mk/main.mk b/mk/main.mk index 3d5d0b441f1..6667a29d4f9 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -14,22 +14,32 @@ # The version number CFG_RELEASE_NUM=0.12.0 -CFG_RELEASE_LABEL=-pre CFG_FILENAME_EXTRA=4e7c5e5c -ifndef CFG_ENABLE_NIGHTLY -# This is the normal version string -CFG_RELEASE=$(CFG_RELEASE_NUM)$(CFG_RELEASE_LABEL) -CFG_PACKAGE_VERS=$(CFG_RELEASE) -else -# Modify the version label for nightly builds -CFG_RELEASE=$(CFG_RELEASE_NUM)$(CFG_RELEASE_LABEL)-nightly -# When building nightly distributables just reuse the same "rust-nightly" name -# so when we upload we'll always override the previous nighly. This doesn't actually -# impact the version reported by rustc - it's just for file naming. +ifeq ($(CFG_RELEASE_CHANNEL),stable) +# This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly" +CFG_RELEASE=$(CFG_RELEASE_NUM) +# This is the string used in dist artifact file names, e.g. "0.12.0", "nightly" +CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM) +endif +ifeq ($(CFG_RELEASE_CHANNEL),beta) +CFG_RELEASE=$(CFG_RELEASE_NUM)-beta +# When building beta/nightly distributables just reuse the same "beta" +# name so when we upload we'll always override the previous +# nighly. This doesn't actually impact the version reported by rustc - +# it's just for file naming. +CFG_PACKAGE_VERS=beta +endif +ifeq ($(CFG_RELEASE_CHANNEL),nightly) +CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly CFG_PACKAGE_VERS=nightly endif +ifeq ($(CFG_RELEASE_CHANNEL),source) +CFG_RELEASE=$(CFG_RELEASE_NUM)-pre +CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-pre +endif + # The name of the package to use for creating tarballs, installers etc. CFG_PACKAGE_NAME=rust-$(CFG_PACKAGE_VERS) diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index 95bcc9ca12b..4a978ccb92b 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -235,7 +235,7 @@ fn partial_sum(start: uint) -> f64 { } fn main() { - let mut futures = Vec::from_fn(1000, |ind| Future::spawn( proc() { partial_sum(ind) })); + let mut futures = Vec::from_fn(200, |ind| Future::spawn( proc() { partial_sum(ind) })); let mut final_res = 0f64; for ft in futures.iter_mut() { diff --git a/src/doc/guide.md b/src/doc/guide.md index cf97cc3ab64..2f16c783446 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -29,8 +29,11 @@ $ curl -s https://static.rust-lang.org/rustup.sh | sudo sh (If you're concerned about `curl | sudo sh`, please keep reading. Disclaimer below.) -If you're on Windows, please [download this .exe and run -it](https://static.rust-lang.org/dist/rust-nightly-install.exe). +If you're on Windows, please download either the [32-bit +installer](https://static.rust-lang.org/dist/rust-nightly-i686-w64-mingw32.exe) +or the [64-bit +installer](https://static.rust-lang.org/dist/rust-nightly-x86_64-w64-mingw32.exe) +and run it. If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay. Not every programming language is great for everyone. Just pass an argument to @@ -185,8 +188,8 @@ Next up is this line: This line does all of the work in our little program. There are a number of details that are important here. The first is that it's indented with four spaces, not tabs. Please configure your editor of choice to insert four spaces -with the tab key. We provide some sample configurations for various editors -[here](https://github.com/rust-lang/rust/tree/master/src/etc). +with the tab key. We provide some [sample configurations for various +editors](https://github.com/rust-lang/rust/tree/master/src/etc). The second point is the `println!()` part. This is calling a Rust **macro**, which is how metaprogramming is done in Rust. If it were a function instead, it @@ -392,14 +395,10 @@ By the way, in these examples, `i` indicates that the number is an integer. Rust is a statically typed language, which means that we specify our types up front. So why does our first example compile? Well, Rust has this thing called -"[Hindley-Milner type -inference](http://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)", -named after some really smart type theorists. If you clicked that link, don't -be scared: what this means for you is that Rust will attempt to infer the types -in your program, and it's pretty good at it. If it can infer the type, Rust +"type inference." If it can figure out what the type of something is, Rust doesn't require you to actually type it out. -We can add the type if we want to. Types come after a colon (`:`): +We can add the type if we want to, though. Types come after a colon (`:`): ```{rust} let x: int = 5; @@ -1281,15 +1280,15 @@ two main looping constructs: `for` and `while`. The `for` loop is used to loop a particular number of times. Rust's `for` loops work a bit differently than in other systems languages, however. Rust's `for` -loop doesn't look like this C `for` loop: +loop doesn't look like this "C style" `for` loop: -```{ignore,c} +```{c} for (x = 0; x < 10; x++) { printf( "%d\n", x ); } ``` -It looks like this: +Instead, it looks like this: ```{rust} for x in range(0i, 10i) { @@ -1312,10 +1311,9 @@ valid for the loop body. Once the body is over, the next value is fetched from the iterator, and we loop another time. When there are no more values, the `for` loop is over. -In our example, the `range` function is a function, provided by Rust, that -takes a start and an end position, and gives an iterator over those values. The -upper bound is exclusive, though, so our loop will print `0` through `9`, not -`10`. +In our example, `range` is a function that takes a start and an end position, +and gives an iterator over those values. The upper bound is exclusive, though, +so our loop will print `0` through `9`, not `10`. Rust does not have the "C style" `for` loop on purpose. Manually controlling each element of the loop is complicated and error prone, even for experienced C diff --git a/src/doc/index.md b/src/doc/index.md index 475c3b748db..f237bc2ddbc 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -86,10 +86,10 @@ There are questions that are asked quite often, and so we've made FAQs for them: # The standard library -You can find function-level documentation for the entire standard library -[here](std/index.html). There's a list of crates on the left with more specific -sections, or you can use the search bar at the top to search for something if -you know its name. +We have [API documentation for the entire standard +library](std/index.html). There's a list of crates on the left with more +specific sections, or you can use the search bar at the top to search for +something if you know its name. # External documentation diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml index cf59f1454c1..2b80c0ff39f 100644 --- a/src/etc/kate/rust.xml +++ b/src/etc/kate/rust.xml @@ -7,7 +7,7 @@ ]> - + fn diff --git a/src/etc/licenseck.py b/src/etc/licenseck.py index 328a2ff6c94..d1b115fc913 100644 --- a/src/etc/licenseck.py +++ b/src/etc/licenseck.py @@ -49,7 +49,6 @@ exceptions = [ "test/bench/shootout-mandelbrot.rs", # BSD "test/bench/shootout-meteor.rs", # BSD "test/bench/shootout-nbody.rs", # BSD - "test/bench/shootout-pidigits.rs", # BSD "test/bench/shootout-regex-dna.rs", # BSD "test/bench/shootout-reverse-complement.rs", # BSD "test/bench/shootout-threadring.rs", # BSD diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 51e1f64e006..349ae15eb32 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -10,9 +10,6 @@ // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` -#[cfg(stage0, not(test))] use core::raw; -#[cfg(stage0, not(test))] use util; - /// Returns a pointer to `size` bytes of memory. /// /// Behavior is undefined if the requested size is 0 or the alignment is not a @@ -111,21 +108,6 @@ unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) { deallocate(ptr, size, align); } -#[cfg(stage0, not(test))] -#[lang="closure_exchange_malloc"] -#[inline] -#[allow(deprecated)] -unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, - align: uint) -> *mut u8 { - let total_size = util::get_box_size(size, align); - let p = allocate(total_size, 8); - - let alloc = p as *mut raw::Box<()>; - (*alloc).drop_glue = drop_glue; - - alloc as *mut u8 -} - // The minimum alignment guaranteed by the architecture. This value is used to // add fast paths for low alignment values. In practice, the alignment is a // constant at the call site and the branch will be optimized out. @@ -155,9 +137,6 @@ mod imp { flags: c_int) -> *mut c_void; fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; - #[cfg(stage0)] - fn je_dallocx(ptr: *mut c_void, flags: c_int); - #[cfg(not(stage0))] fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); fn je_nallocx(size: size_t, flags: c_int) -> size_t; fn je_malloc_stats_print(write_cb: Option { - String(&'a str), - Argument(Argument<'a>), -} - #[doc(hidden)] pub struct Argument<'a> { pub position: Position, diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 6837f3b9af7..7e399902a4b 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -419,8 +419,76 @@ struct TwoWaySearcher { memory: uint } -// This is the Two-Way search algorithm, which was introduced in the paper: -// Crochemore, M., Perrin, D., 1991, Two-way string-matching, Journal of the ACM 38(3):651-675. +/* + This is the Two-Way search algorithm, which was introduced in the paper: + Crochemore, M., Perrin, D., 1991, Two-way string-matching, Journal of the ACM 38(3):651-675. + + Here's some background information. + + A *word* is a string of symbols. The *length* of a word should be a familiar + notion, and here we denote it for any word x by |x|. + (We also allow for the possibility of the *empty word*, a word of length zero). + + If x is any non-empty word, then an integer p with 0 < p <= |x| is said to be a + *period* for x iff for all i with 0 <= i <= |x| - p - 1, we have x[i] == x[i+p]. + For example, both 1 and 2 are periods for the string "aa". As another example, + the only period of the string "abcd" is 4. + + We denote by period(x) the *smallest* period of x (provided that x is non-empty). + This is always well-defined since every non-empty word x has at least one period, + |x|. We sometimes call this *the period* of x. + + If u, v and x are words such that x = uv, where uv is the concatenation of u and + v, then we say that (u, v) is a *factorization* of x. + + Let (u, v) be a factorization for a word x. Then if w is a non-empty word such + that both of the following hold + + - either w is a suffix of u or u is a suffix of w + - either w is a prefix of v or v is a prefix of w + + then w is said to be a *repetition* for the factorization (u, v). + + Just to unpack this, there are four possibilities here. Let w = "abc". Then we + might have: + + - w is a suffix of u and w is a prefix of v. ex: ("lolabc", "abcde") + - w is a suffix of u and v is a prefix of w. ex: ("lolabc", "ab") + - u is a suffix of w and w is a prefix of v. ex: ("bc", "abchi") + - u is a suffix of w and v is a prefix of w. ex: ("bc", "a") + + Note that the word vu is a repetition for any factorization (u,v) of x = uv, + so every factorization has at least one repetition. + + If x is a string and (u, v) is a factorization for x, then a *local period* for + (u, v) is an integer r such that there is some word w such that |w| = r and w is + a repetition for (u, v). + + We denote by local_period(u, v) the smallest local period of (u, v). We sometimes + call this *the local period* of (u, v). Provided that x = uv is non-empty, this + is well-defined (because each non-empty word has at least one factorization, as + noted above). + + It can be proven that the following is an equivalent definition of a local period + for a factorization (u, v): any positive integer r such that x[i] == x[i+r] for + all i such that |u| - r <= i <= |u| - 1 and such that both x[i] and x[i+r] are + defined. (i.e. i > 0 and i + r < |x|). + + Using the above reformulation, it is easy to prove that + + 1 <= local_period(u, v) <= period(uv) + + A factorization (u, v) of x such that local_period(u,v) = period(x) is called a + *critical factorization*. + + The algorithm hinges on the following theorem, which is stated without proof: + + **Critical Factorization Theorem** Any word x has at least one critical + factorization (u, v) such that |u| < period(x). + + The purpose of maximal_suffix is to find such a critical factorization. + +*/ impl TwoWaySearcher { fn new(needle: &[u8]) -> TwoWaySearcher { let (crit_pos1, period1) = TwoWaySearcher::maximal_suffix(needle, false); @@ -436,15 +504,19 @@ impl TwoWaySearcher { period = period2; } + // This isn't in the original algorithm, as far as I'm aware. let byteset = needle.iter() .fold(0, |a, &b| (1 << ((b & 0x3f) as uint)) | a); - // The logic here (calculating crit_pos and period, the final if statement to see which - // period to use for the TwoWaySearcher) is essentially an implementation of the - // "small-period" function from the paper (p. 670) + // A particularly readable explanation of what's going on here can be found + // in Crochemore and Rytter's book "Text Algorithms", ch 13. Specifically + // see the code for "Algorithm CP" on p. 323. // - // In the paper they check whether `needle.slice_to(crit_pos)` is a suffix of - // `needle.slice(crit_pos, crit_pos + period)`, which is precisely what this does + // What's going on is we have some critical factorization (u, v) of the + // needle, and we want to determine whether u is a suffix of + // v.slice_to(period). If it is, we use "Algorithm CP1". Otherwise we use + // "Algorithm CP2", which is optimized for when the period of the needle + // is large. if needle.slice_to(crit_pos) == needle.slice(period, period + crit_pos) { TwoWaySearcher { crit_pos: crit_pos, @@ -466,6 +538,11 @@ impl TwoWaySearcher { } } + // One of the main ideas of Two-Way is that we factorize the needle into + // two halves, (u, v), and begin trying to find v in the haystack by scanning + // left to right. If v matches, we try to match u by scanning right to left. + // How far we can jump when we encounter a mismatch is all based on the fact + // that (u, v) is a critical factorization for the needle. #[inline] fn next(&mut self, haystack: &[u8], needle: &[u8], long_period: bool) -> Option<(uint, uint)> { 'search: loop { @@ -479,6 +556,9 @@ impl TwoWaySearcher { ((haystack[self.position + needle.len() - 1] & 0x3f) as uint)) & 1 == 0 { self.position += needle.len(); + if !long_period { + self.memory = 0; + } continue 'search; } @@ -517,9 +597,9 @@ impl TwoWaySearcher { } } - // returns (i, p) where i is the "critical position", the starting index of - // of maximal suffix, and p is the period of the suffix - // see p. 668 of the paper + // Computes a critical factorization (u, v) of `arr`. + // Specifically, returns (i, p), where i is the starting index of v in some + // critical factorization (u, v) and p = period(v) #[inline] fn maximal_suffix(arr: &[u8], reversed: bool) -> (uint, uint) { let mut left = -1; // Corresponds to i in the paper diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index be2275dcd4a..51bd72ec014 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -26,6 +26,12 @@ fn strslice_issue_16589() { check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd"); } +#[test] +fn strslice_issue_16878() { + assert!(!"1234567ah012345678901ah".contains("hah")); + assert!(!"00abc01234567890123456789abc".contains("bcabc")); +} + #[test] fn test_strslice_contains() { diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index c97f9513fc3..3f91ce11915 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -19,6 +19,7 @@ //! ## Example //! //! ```rust +//! # #![allow(deprecated)] //! use num::bigint::BigUint; //! use std::num::{Zero, One}; //! use std::mem::replace; @@ -42,6 +43,7 @@ //! It's easy to generate large random numbers: //! //! ```rust +//! # #![allow(deprecated)] //! use num::bigint::{ToBigInt, RandBigInt}; //! use std::rand; //! diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs index f12279b20e8..17071d22dee 100644 --- a/src/libnum/lib.rs +++ b/src/libnum/lib.rs @@ -18,6 +18,7 @@ //! approximate a square root to arbitrary precision: //! //! ``` +//! # #![allow(deprecated)] //! extern crate num; //! //! use num::bigint::BigInt; @@ -46,7 +47,9 @@ #![feature(default_type_params)] #![crate_name = "num"] -#![experimental] +#![deprecated = "This is now a cargo package located at: \ + https://github.com/rust-lang/num"] +#![allow(deprecated)] #![crate_type = "rlib"] #![crate_type = "dylib"] #![license = "MIT/ASL2"] diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 079e01c6ed6..14cf07cd5e4 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -109,11 +109,6 @@ register_diagnostics!( E0092, E0093, E0094, - E0095, - E0096, - E0097, - E0098, - E0099, E0100, E0101, E0102, @@ -153,7 +148,6 @@ register_diagnostics!( E0139, E0140, E0141, - E0142, E0143, E0144, E0145, @@ -169,6 +163,5 @@ register_diagnostics!( E0157, E0158, E0159, - E0160, E0161 ) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index eed41edac9d..836d355d55b 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -689,11 +689,7 @@ impl LintPass for UnusedResult { ast::StmtSemi(ref expr, _) => &**expr, _ => return }; - let t = ty::expr_ty(cx.tcx, expr); - match ty::get(t).sty { - ty::ty_nil | ty::ty_bot | ty::ty_bool => return, - _ => {} - } + match expr.node { ast::ExprRet(..) => return, _ => {} @@ -702,6 +698,7 @@ impl LintPass for UnusedResult { let t = ty::expr_ty(cx.tcx, expr); let mut warned = false; match ty::get(t).sty { + ty::ty_nil | ty::ty_bot | ty::ty_bool => return, ty::ty_struct(did, _) | ty::ty_enum(did, _) => { if ast_util::is_local(did) { @@ -1107,6 +1104,41 @@ impl LintPass for UnnecessaryParens { } } +declare_lint!(UNNECESSARY_IMPORT_BRACES, Allow, + "unnecessary braces around an imported item") + +pub struct UnnecessaryImportBraces; + +impl LintPass for UnnecessaryImportBraces { + fn get_lints(&self) -> LintArray { + lint_array!(UNNECESSARY_IMPORT_BRACES) + } + + fn check_view_item(&mut self, cx: &Context, view_item: &ast::ViewItem) { + match view_item.node { + ast::ViewItemUse(ref view_path) => { + match view_path.node { + ast::ViewPathList(_, ref items, _) => { + if items.len() == 1 { + match items[0].node { + ast::PathListIdent {ref name, ..} => { + let m = format!("braces around {} is unnecessary", + token::get_ident(*name).get()); + cx.span_lint(UNNECESSARY_IMPORT_BRACES, view_item.span, + m.as_slice()); + }, + _ => () + } + } + } + _ => () + } + }, + _ => () + } + } +} + declare_lint!(UNUSED_UNSAFE, Warn, "unnecessary use of an `unsafe` block") diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index c75b57dcafa..e39685705df 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -183,6 +183,7 @@ impl LintStore { NonSnakeCase, NonUppercaseStatics, UnnecessaryParens, + UnnecessaryImportBraces, UnusedUnsafe, UnsafeBlock, UnusedMut, diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index c7af7b24939..748e59b75ed 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -325,7 +325,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) }; DlDef(def::DefStaticMethod(did, provenance, fn_style)) } - Type | ForeignType => DlDef(def::DefTy(did)), + Type | ForeignType => DlDef(def::DefTy(did, false)), Mod => DlDef(def::DefMod(did)), ForeignMod => DlDef(def::DefForeignMod(did)), StructVariant => { @@ -337,7 +337,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) DlDef(def::DefVariant(enum_did, did, false)) } Trait => DlDef(def::DefTrait(did)), - Enum => DlDef(def::DefTy(did)), + Enum => DlDef(def::DefTy(did, true)), Impl => DlImpl(did), PublicField | InheritedField => DlField, } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 53203663bb1..0e888b39b85 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -680,14 +680,14 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds { let builtin_bounds = parse_builtin_bounds(st, |x,y| conv(x,y)); let mut param_bounds = ty::ParamBounds { - opt_region_bound: None, + region_bounds: Vec::new(), builtin_bounds: builtin_bounds, trait_bounds: Vec::new() }; loop { match next(st) { 'R' => { - param_bounds.opt_region_bound = Some(parse_region(st, |x, y| conv (x, y))); + param_bounds.region_bounds.push(parse_region(st, |x, y| conv (x, y))); } 'I' => { param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y)))); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index cbf558b6b48..3ef1d15cf56 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -366,7 +366,7 @@ pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::Exi pub fn enc_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ParamBounds) { enc_builtin_bounds(w, cx, &bs.builtin_bounds); - for &r in bs.opt_region_bound.iter() { + for &r in bs.region_bounds.iter() { mywrite!(w, "R"); enc_region(w, cx, r); } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 272b7111fb8..880445ff38d 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -454,7 +454,7 @@ impl tr for def::Def { def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s) }, def::DefTrait(did) => def::DefTrait(did.tr(dcx)), - def::DefTy(did) => def::DefTy(did.tr(dcx)), + def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum), def::DefPrimTy(p) => def::DefPrimTy(p), def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(dcx), v), def::DefBinding(nid, bm) => def::DefBinding(dcx.tr_id(nid), bm), diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 914cf451ebe..70a9b6c5337 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -25,7 +25,7 @@ pub enum Def { DefArg(ast::NodeId, ast::BindingMode), DefLocal(ast::NodeId, ast::BindingMode), DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */), - DefTy(ast::DefId), + DefTy(ast::DefId, bool /* is_enum */), DefTrait(ast::DefId), DefPrimTy(ast::PrimTy), DefTyParam(ParamSpace, ast::DefId, uint), @@ -62,7 +62,7 @@ impl Def { match *self { DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) | - DefVariant(_, id, _) | DefTy(id) | DefTyParam(_, id, _) | + DefVariant(_, id, _) | DefTy(id, _) | DefTyParam(_, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => { id } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index aecfa36c108..fee6c77a799 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -131,8 +131,8 @@ enum LoopKind<'a> { LoopLoop, /// A `while` loop, with the given expression as condition. WhileLoop(&'a Expr), - /// A `for` loop. - ForLoop, + /// A `for` loop, with the given pattern to bind. + ForLoop(&'a Pat), } #[deriving(PartialEq)] @@ -1024,8 +1024,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_loop(expr, WhileLoop(&**cond), &**blk, succ) } - ExprForLoop(_, ref head, ref blk, _) => { - let ln = self.propagate_through_loop(expr, ForLoop, &**blk, succ); + ExprForLoop(ref pat, ref head, ref blk, _) => { + let ln = self.propagate_through_loop(expr, ForLoop(&**pat), &**blk, succ); self.propagate_through_expr(&**head, ln) } @@ -1355,7 +1355,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { expr.id, block_to_string(body)); let cond_ln = match kind { - LoopLoop | ForLoop => ln, + LoopLoop => ln, + ForLoop(ref pat) => self.define_bindings_in_pat(*pat, ln), WhileLoop(ref cond) => self.propagate_through_expr(&**cond, ln), }; let body_ln = self.with_loop_nodes(expr.id, succ, ln, |this| { @@ -1367,7 +1368,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { first_merge = false; let new_cond_ln = match kind { - LoopLoop | ForLoop => ln, + LoopLoop => ln, + ForLoop(ref pat) => { + self.define_bindings_in_pat(*pat, ln) + } WhileLoop(ref cond) => { self.propagate_through_expr(&**cond, ln) } @@ -1453,6 +1457,12 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { visit::walk_expr(this, expr); } + ExprForLoop(ref pat, _, _, _) => { + this.pat_bindings(&**pat, |this, ln, var, sp, id| { + this.warn_about_unused(sp, id, ln, var); + }); + } + // no correctness conditions related to liveness ExprCall(..) | ExprMethodCall(..) | ExprIf(..) | ExprMatch(..) | ExprWhile(..) | ExprLoop(..) | ExprIndex(..) | ExprField(..) | @@ -1461,7 +1471,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { ExprAgain(..) | ExprLit(_) | ExprBlock(..) | ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) | ExprParen(..) | ExprFnBlock(..) | ExprProc(..) | ExprUnboxedFn(..) | - ExprPath(..) | ExprBox(..) | ExprForLoop(..) => { + ExprPath(..) | ExprBox(..) => { visit::walk_expr(this, expr); } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3e42ee9187c..4f9cc9c080f 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -531,7 +531,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { Ok(self.cat_rvalue_node(id, span, expr_ty)) } def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) | - def::DefTrait(_) | def::DefTy(_) | def::DefPrimTy(_) | + def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) | def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) => { Ok(Rc::new(cmt_ { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 56c785d3c25..0eb684fe18e 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -771,7 +771,8 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { def::DefFn(..) => ck("function"), def::DefStatic(..) => ck("static"), def::DefVariant(..) => ck("variant"), - def::DefTy(..) => ck("type"), + def::DefTy(_, false) => ck("type"), + def::DefTy(_, true) => ck("enum"), def::DefTrait(..) => ck("trait"), def::DefStruct(..) => ck("struct"), def::DefMethod(_, Some(..)) => ck("trait method"), diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index d4fe3c265f5..861ac2ffe60 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1252,7 +1252,7 @@ impl<'a> Resolver<'a> { sp); name_bindings.define_type - (DefTy(local_def(item.id)), sp, is_public); + (DefTy(local_def(item.id), false), sp, is_public); parent } @@ -1264,7 +1264,7 @@ impl<'a> Resolver<'a> { sp); name_bindings.define_type - (DefTy(local_def(item.id)), sp, is_public); + (DefTy(local_def(item.id), true), sp, is_public); for variant in (*enum_definition).variants.iter() { self.build_reduced_graph_for_variant( @@ -1287,7 +1287,7 @@ impl<'a> Resolver<'a> { let name_bindings = self.add_child(ident, parent.clone(), forbid, sp); // Define a name in the type namespace. - name_bindings.define_type(DefTy(local_def(item.id)), sp, is_public); + name_bindings.define_type(DefTy(local_def(item.id), false), sp, is_public); // If this is a newtype or unit-like struct, define a name // in the value namespace as well @@ -1732,7 +1732,7 @@ impl<'a> Resolver<'a> { match def { DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) | - DefTy(def_id) => { + DefTy(def_id, _) => { let type_def = child_name_bindings.type_def.borrow().clone(); match type_def { Some(TypeNsDef { module_def: Some(module_def), .. }) => { @@ -1823,7 +1823,7 @@ impl<'a> Resolver<'a> { is_public, DUMMY_SP) } - DefTy(_) => { + DefTy(..) => { debug!("(building reduced graph for external \ crate) building type {}", final_ident); @@ -4320,7 +4320,7 @@ impl<'a> Resolver<'a> { // If it's a typedef, give a note match def { - DefTy(_) => { + DefTy(..) => { self.session.span_note( trait_reference.path.span, format!("`type` aliases cannot \ @@ -4381,7 +4381,7 @@ impl<'a> Resolver<'a> { Some(ref t) => match t.node { TyPath(ref path, None, path_id) => { match this.resolve_path(id, path, TypeNS, true) { - Some((DefTy(def_id), lp)) if this.structs.contains_key(&def_id) => { + Some((DefTy(def_id, _), lp)) if this.structs.contains_key(&def_id) => { let def = DefStruct(def_id); debug!("(resolving struct) resolved `{}` to type {:?}", token::get_ident(path.segments @@ -5440,7 +5440,7 @@ impl<'a> Resolver<'a> { if allowed == Everything { // Look for a field with the same name in the current self_type. match self.def_map.borrow().find(&node_id) { - Some(&DefTy(did)) + Some(&DefTy(did, _)) | Some(&DefStruct(did)) | Some(&DefVariant(_, did, _)) => match self.structs.find(&did) { None => {} @@ -5582,7 +5582,7 @@ impl<'a> Resolver<'a> { // structs, which wouldn't result in this error.) match self.with_no_errors(|this| this.resolve_path(expr.id, path, TypeNS, false)) { - Some((DefTy(struct_id), _)) + Some((DefTy(struct_id, _), _)) if self.structs.contains_key(&struct_id) => { self.resolve_error(expr.span, format!("`{}` is a structure name, but \ diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs index fe066c732dd..37ba3b75f89 100644 --- a/src/librustc/middle/save/mod.rs +++ b/src/librustc/middle/save/mod.rs @@ -226,7 +226,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefMod(_) | def::DefForeignMod(_) => Some(recorder::ModRef), def::DefStruct(_) => Some(recorder::StructRef), - def::DefTy(_) | + def::DefTy(..) | def::DefTrait(_) => Some(recorder::TypeRef), def::DefStatic(_, _) | def::DefBinding(_, _) | diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 11b954f2ba6..1eae4ac1932 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -250,9 +250,7 @@ pub fn search_trait_and_supertraits_from_bound(tcx: &ty::ctxt, * is the path to that trait/supertrait. Else `None`. */ - for (bound_index, bound) in - transitive_bounds(tcx, &[caller_bound]).enumerate() - { + for bound in transitive_bounds(tcx, &[caller_bound]) { if test(bound.def_id) { let vtable_param = VtableParam { bound: bound }; return Some(vtable_param); diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 3b670dc04fd..51023d03c23 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -557,7 +557,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let tcx = bcx.tcx(); let mut found: Vec = vec![]; - for (i, br) in m.iter().enumerate() { + for br in m.iter() { let cur = *br.pats.get(col); let opt = match cur.node { ast::PatLit(ref l) => ConstantValue(ConstantExpr(&**l)), diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index af57d49d9d8..77712570185 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1380,7 +1380,11 @@ pub fn trans_adt<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, assert_eq!(discr, 0); match ty::expr_kind(bcx.tcx(), &*base.expr) { - ty::LvalueExpr => { + ty::RvalueDpsExpr | ty::RvalueDatumExpr if !ty::type_needs_drop(bcx.tcx(), ty) => { + bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); + }, + ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"), + _ => { let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base")); for &(i, t) in base.fields.iter() { let datum = base_datum.get_element( @@ -1389,11 +1393,7 @@ pub fn trans_adt<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); bcx = datum.store_to(bcx, dest); } - }, - ty::RvalueDpsExpr | ty::RvalueDatumExpr => { - bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); - }, - ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr") + } } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index bd472195b95..09912b54583 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1008,7 +1008,7 @@ pub enum type_err { /// as well as the existential type parameter in an object type. #[deriving(PartialEq, Eq, Hash, Clone, Show)] pub struct ParamBounds { - pub opt_region_bound: Option, + pub region_bounds: Vec, pub builtin_bounds: BuiltinBounds, pub trait_bounds: Vec> } @@ -1016,7 +1016,8 @@ pub struct ParamBounds { /// Bounds suitable for an existentially quantified type parameter /// such as those that appear in object types or closure types. The /// major difference between this case and `ParamBounds` is that -/// general purpose trait bounds are omitted. +/// general purpose trait bounds are omitted and there must be +/// *exactly one* region. #[deriving(PartialEq, Eq, Hash, Clone, Show)] pub struct ExistentialBounds { pub region_bound: ty::Region, @@ -3789,7 +3790,8 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String { ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)), ty_box(_) => "Gc-ptr".to_string(), ty_uniq(_) => "box".to_string(), - ty_vec(_, _) => "vector".to_string(), + ty_vec(_, Some(_)) => "array".to_string(), + ty_vec(_, None) => "unsized array".to_string(), ty_ptr(_) => "*-ptr".to_string(), ty_rptr(_, _) => "&-ptr".to_string(), ty_bare_fn(_) => "extern fn".to_string(), @@ -4864,7 +4866,7 @@ pub fn required_region_bounds(tcx: &ctxt, trait_bounds, |trait_ref| { let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref); - push_region_bounds(bounds.opt_region_bound.as_slice(), + push_region_bounds(bounds.region_bounds.as_slice(), bounds.builtin_bounds, &mut all_bounds); debug!("from {}: bounds={} all_bounds={}", diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 549f0daef81..48fa6f823b0 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -287,7 +287,7 @@ impl TypeFoldable for ty::ExistentialBounds { impl TypeFoldable for ty::ParamBounds { fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParamBounds { ty::ParamBounds { - opt_region_bound: self.opt_region_bound.fold_with(folder), + region_bounds: self.region_bounds.fold_with(folder), builtin_bounds: self.builtin_bounds.fold_with(folder), trait_bounds: self.trait_bounds.fold_with(folder), } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index c46e95cf045..00678eb6380 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -438,7 +438,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( // FIXME(#12938): This is a hack until we have full support for // DST. match a_def { - def::DefTy(did) | def::DefStruct(did) + def::DefTy(did, _) | def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => { if path.segments .iter() @@ -462,7 +462,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( "not enough type parameters supplied to `Box`"); Some(ty::mk_err()) } - def::DefTy(did) | def::DefStruct(did) + def::DefTy(did, _) | def::DefStruct(did) if Some(did) == this.tcx().lang_items.gc() => { if path.segments .iter() @@ -833,7 +833,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( result.substs.clone(), bounds) } - def::DefTy(did) | def::DefStruct(did) => { + def::DefTy(did, _) | def::DefStruct(did) => { ast_path_to_ty(this, rscope, did, path).ty } def::DefTyParam(space, id, n) => { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 12905763f52..2f5b6e1fa03 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2005,7 +2005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let region_bounds = ty::required_region_bounds( self.tcx(), - param_bound.opt_region_bound.as_slice(), + param_bound.region_bounds.as_slice(), param_bound.builtin_bounds, param_bound.trait_bounds.as_slice()); for &r in region_bounds.iter() { @@ -4937,7 +4937,7 @@ pub fn polytype_for_def(fcx: &FnCtxt, return polytype_for_def(fcx, sp, *inner); } def::DefTrait(_) | - def::DefTy(_) | + def::DefTy(..) | def::DefPrimTy(_) | def::DefTyParam(..)=> { fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type"); diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 37b77e872ca..a8f2a8f6f1d 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -1880,7 +1880,7 @@ fn param_must_outlive(rcx: &Rcx, let param_bound = param_env.bounds.get(param_ty.space, param_ty.idx); param_bounds = ty::required_region_bounds(rcx.tcx(), - param_bound.opt_region_bound.as_slice(), + param_bound.region_bounds.as_slice(), param_bound.builtin_bounds, param_bound.trait_bounds.as_slice()); diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 60e502786ab..8bcbe4b7929 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -327,7 +327,7 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { // Inspect bounds on this type parameter for any // region bounds. - for &r in type_param_def.bounds.opt_region_bound.iter() { + for &r in type_param_def.bounds.region_bounds.iter() { self.stack.push((r, Some(ty))); self.accumulate_from_ty(type_param_ty); self.stack.pop().unwrap(); diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index c7b4a78492b..dedb860967c 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1044,7 +1044,7 @@ fn ty_generics_for_trait(ccx: &CrateCtxt, ident: special_idents::type_self, def_id: local_def(param_id), bounds: ty::ParamBounds { - opt_region_bound: None, + region_bounds: vec!(), builtin_bounds: ty::empty_builtin_bounds(), trait_bounds: vec!(self_trait_ref), }, @@ -1280,12 +1280,12 @@ fn conv_param_bounds(ccx: &CrateCtxt, .map(|b| instantiate_trait_ref(ccx, b, param_ty.to_ty(ccx.tcx))) .chain(unboxed_fn_ty_bounds) .collect(); - let opt_region_bound = - astconv::compute_opt_region_bound( - ccx.tcx, span, builtin_bounds, region_bounds.as_slice(), - trait_bounds.as_slice()); + let region_bounds: Vec = + region_bounds.move_iter() + .map(|r| ast_region_to_region(ccx.tcx, r)) + .collect(); ty::ParamBounds { - opt_region_bound: opt_region_bound, + region_bounds: region_bounds, builtin_bounds: builtin_bounds, trait_bounds: trait_bounds, } diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index 499740a78ef..af670f25e56 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -1235,7 +1235,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { Some(&d) => d }; match a_def { - def::DefTy(did) | def::DefStruct(did) => { + def::DefTy(did, _) | def::DefStruct(did) => { let generics = ty::lookup_item_type(self.tcx, did).generics; let expected = diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index ccff8afc50b..ccb01ca620e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -87,7 +87,12 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt, ret.extend(build_impls(cx, tcx, did).into_iter()); clean::StructItem(build_struct(cx, tcx, did)) } - def::DefTy(did) => { + def::DefTy(did, false) => { + record_extern_fqn(cx, did, clean::TypeTypedef); + ret.extend(build_impls(cx, tcx, did).into_iter()); + build_type(cx, tcx, did) + } + def::DefTy(did, true) => { record_extern_fqn(cx, did, clean::TypeEnum); ret.extend(build_impls(cx, tcx, did).into_iter()); build_type(cx, tcx, did) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c42d8c79144..c03c56cd223 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1094,6 +1094,7 @@ pub enum TypeKind { TypeStruct, TypeTrait, TypeVariant, + TypeTypedef, } impl Primitive { @@ -2049,7 +2050,8 @@ fn resolve_type(cx: &DocContext, path: Path, fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId { let (did, kind) = match def { def::DefFn(i, _) => (i, TypeFunction), - def::DefTy(i) => (i, TypeEnum), + def::DefTy(i, false) => (i, TypeTypedef), + def::DefTy(i, true) => (i, TypeEnum), def::DefTrait(i) => (i, TypeTrait), def::DefStruct(i) => (i, TypeStruct), def::DefMod(i) => (i, TypeModule), diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index f36c81f8f8d..6e240b0d8d4 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -45,7 +45,7 @@ impl ItemType { match *self { Module => "mod", Struct => "struct", - Enum => "type", + Enum => "enum", Function => "fn", Typedef => "type", Static => "static", diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 169446b0ac0..a0c4283711e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -308,6 +308,7 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) -> clean::TypeModule => item_type::Module, clean::TypeStatic => item_type::Static, clean::TypeVariant => item_type::Variant, + clean::TypeTypedef => item_type::Typedef, })) }).collect() }).unwrap_or(HashMap::new()); diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 27d54f8ec9d..7eec634405b 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -229,6 +229,8 @@ nav.sub { .content .highlighted.enum { background-color: #b4d1b9; } .content .highlighted.struct { background-color: #e7b1a0; } .content .highlighted.fn { background-color: #c6afb3; } +.content .highlighted.method { background-color: #c6afb3; } +.content .highlighted.ffi { background-color: #c6afb3; } .docblock.short.nowrap { display: block; @@ -336,11 +338,13 @@ a { p a { color: #4e8bca; } p a:hover { text-decoration: underline; } -.content span.trait, .block a.current.trait { color: #ed9603; } -.content span.mod, .block a.current.mod { color: #4d76ae; } -.content span.enum, .block a.current.enum { color: #5e9766; } -.content span.struct, .block a.current.struct { color: #e53700; } -.content span.fn, .block a.current.fn { color: #8c6067; } +.content span.trait, .content a.trait, .block a.current.trait { color: #ed9603; } +.content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; } +.content span.enum, .content a.enum, .block a.current.enum { color: #5e9766; } +.content span.struct, .content a.struct, .block a.current.struct { color: #e53700; } +.content span.fn, .content a.fn, .block a.current.fn { color: #8c6067; } +.content span.method, .content a.method, .block a.current.method { color: #8c6067; } +.content span.ffi, .content a.ffi, .block a.current.ffi { color: #8c6067; } .content .fnname { color: #8c6067; } .search-input { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index ad9557bf2c1..6992a966592 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -555,7 +555,7 @@ // `rustdoc::html::item_type::ItemType` type in Rust. var itemTypes = ["mod", "struct", - "type", + "enum", "fn", "type", "static", diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index e9c3a2afb03..833c5cd0f98 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -234,6 +234,7 @@ pub enum ErrorCode { KeyMustBeAString, ExpectedColon, TrailingCharacters, + TrailingComma, InvalidEscape, InvalidUnicodeCodePoint, LoneLeadingSurrogateInHexEscape, @@ -274,6 +275,7 @@ pub fn error_str(error: ErrorCode) -> &'static str { KeyMustBeAString => "key must be a string", ExpectedColon => "expected `:`", TrailingCharacters => "trailing characters", + TrailingComma => "trailing comma", InvalidEscape => "invalid escape", UnrecognizedHex => "invalid \\u escape (unrecognized hex)", NotFourDigit => "invalid \\u escape (not four digits)", @@ -1681,7 +1683,11 @@ impl> Parser { fn parse_object(&mut self, first: bool) -> JsonEvent { if self.ch_is('}') { if !first { - self.stack.pop(); + if self.stack.is_empty() { + return self.error_event(TrailingComma); + } else { + self.stack.pop(); + } } if self.stack.is_empty() { self.state = ParseBeforeFinish; @@ -2377,7 +2383,7 @@ mod tests { F64Value, StringValue, NullValue, SyntaxError, Key, Index, Stack, InvalidSyntax, InvalidNumber, EOFWhileParsingObject, EOFWhileParsingList, EOFWhileParsingValue, EOFWhileParsingString, KeyMustBeAString, ExpectedColon, - TrailingCharacters}; + TrailingCharacters, TrailingComma}; use std::{i64, u64, f32, f64, io}; use std::collections::TreeMap; @@ -3379,6 +3385,7 @@ mod tests { } } } + #[test] #[ignore(cfg(target_word_size = "32"))] // FIXME(#14064) fn test_read_object_streaming() { @@ -3393,6 +3400,7 @@ mod tests { assert_eq!(last_event("{\"a\":1"), Error(SyntaxError(EOFWhileParsingObject, 1, 7))); assert_eq!(last_event("{\"a\":1 1"), Error(SyntaxError(InvalidSyntax, 1, 8))); assert_eq!(last_event("{\"a\":1,"), Error(SyntaxError(EOFWhileParsingObject, 1, 8))); + assert_eq!(last_event("{\"a\":1,}"), Error(SyntaxError(TrailingComma, 1, 8))); assert_stream_equal( "{}", diff --git a/src/libstd/io/net/mod.rs b/src/libstd/io/net/mod.rs index 54af83462ee..4bd998d5ed9 100644 --- a/src/libstd/io/net/mod.rs +++ b/src/libstd/io/net/mod.rs @@ -19,8 +19,7 @@ pub mod addrinfo; pub mod tcp; pub mod udp; pub mod ip; -// FIXME(#12093) - this should not be called unix -pub mod unix; +pub mod pipe; fn to_rtio(ip: IpAddr) -> rtio::IpAddr { match ip { diff --git a/src/libstd/io/net/unix.rs b/src/libstd/io/net/pipe.rs similarity index 99% rename from src/libstd/io/net/unix.rs rename to src/libstd/io/net/pipe.rs index ea851d44531..bdd58b07d86 100644 --- a/src/libstd/io/net/unix.rs +++ b/src/libstd/io/net/pipe.rs @@ -46,7 +46,7 @@ impl UnixStream { /// /// ```rust /// # #![allow(unused_must_use)] - /// use std::io::net::unix::UnixStream; + /// use std::io::net::pipe::UnixStream; /// /// let server = Path::new("path/to/my/socket"); /// let mut stream = UnixStream::connect(&server); @@ -164,7 +164,7 @@ impl UnixListener { /// # fn main() {} /// # fn foo() { /// # #![allow(unused_must_use)] - /// use std::io::net::unix::UnixListener; + /// use std::io::net::pipe::UnixListener; /// use std::io::{Listener, Acceptor}; /// /// let server = Path::new("/path/to/my/socket"); diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index 78d1a2f485a..cfc5fb982b8 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -34,7 +34,7 @@ macro_rules! iotest ( use io::net::ip::*; use io::net::udp::*; #[cfg(unix)] - use io::net::unix::*; + use io::net::pipe::*; use io::timer::*; use io::process::*; use rt::running_on_valgrind; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 0ebca006c4c..e1f2f43673f 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -434,8 +434,8 @@ pub mod builtin { /// # Example /// /// ```rust - /// let home: &'static str = env!("HOME"); - /// println!("the home directory at the time of compiling was: {}", home); + /// let path: &'static str = env!("PATH"); + /// println!("the $PATH variable at the time of compiling was: {}", path); /// ``` #[macro_export] macro_rules! env( ($name:expr) => ({ /* compiler built-in */ }) ) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0db1f2282a6..ea392c87723 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -88,14 +88,13 @@ use std::mem; use std::rc::Rc; use std::iter; -#[allow(non_camel_case_types)] -#[deriving(PartialEq)] -pub enum restriction { - UNRESTRICTED, - RESTRICT_STMT_EXPR, - RESTRICT_NO_BAR_OP, - RESTRICT_NO_BAR_OR_DOUBLEBAR_OP, - RESTRICT_NO_STRUCT_LITERAL, +bitflags! { + flags Restrictions: u8 { + static Unrestricted = 0b0000, + static RestrictionStmtExpr = 0b0001, + static RestrictionNoBarOp = 0b0010, + static RestrictionNoStructLiteral = 0b0100 + } } type ItemInfo = (Ident, Item_, Option >); @@ -314,7 +313,7 @@ pub struct Parser<'a> { pub buffer_start: int, pub buffer_end: int, pub tokens_consumed: uint, - pub restriction: restriction, + pub restrictions: Restrictions, pub quote_depth: uint, // not (yet) related to the quasiquoter pub reader: Box, pub interner: Rc, @@ -383,7 +382,7 @@ impl<'a> Parser<'a> { buffer_start: 0, buffer_end: 0, tokens_consumed: 0, - restriction: UNRESTRICTED, + restrictions: Unrestricted, quote_depth: 0, obsolete_set: HashSet::new(), mod_path_stack: Vec::new(), @@ -2189,7 +2188,7 @@ impl<'a> Parser<'a> { if self.token == token::LBRACE { // This is a struct literal, unless we're prohibited // from parsing struct literals here. - if self.restriction != RESTRICT_NO_STRUCT_LITERAL { + if !self.restrictions.contains(RestrictionNoStructLiteral) { // It's a struct literal. self.bump(); let mut fields = Vec::new(); @@ -2651,12 +2650,9 @@ impl<'a> Parser<'a> { // Prevent dynamic borrow errors later on by limiting the // scope of the borrows. - match (&self.token, &self.restriction) { - (&token::BINOP(token::OR), &RESTRICT_NO_BAR_OP) => return lhs, - (&token::BINOP(token::OR), - &RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) => return lhs, - (&token::OROR, &RESTRICT_NO_BAR_OR_DOUBLEBAR_OP) => return lhs, - _ => { } + if self.token == token::BINOP(token::OR) && + self.restrictions.contains(RestrictionNoBarOp) { + return lhs; } let cur_opt = token_to_binop(&self.token); @@ -2696,15 +2692,16 @@ impl<'a> Parser<'a> { pub fn parse_assign_expr(&mut self) -> P { let lo = self.span.lo; let lhs = self.parse_binops(); + let restrictions = self.restrictions & RestrictionNoStructLiteral; match self.token { token::EQ => { self.bump(); - let rhs = self.parse_expr(); + let rhs = self.parse_expr_res(restrictions); self.mk_expr(lo, rhs.span.hi, ExprAssign(lhs, rhs)) } token::BINOPEQ(op) => { self.bump(); - let rhs = self.parse_expr(); + let rhs = self.parse_expr_res(restrictions); let aop = match op { token::PLUS => BiAdd, token::MINUS => BiSub, @@ -2730,7 +2727,7 @@ impl<'a> Parser<'a> { /// Parse an 'if' expression ('if' token already eaten) pub fn parse_if_expr(&mut self) -> P { let lo = self.last_span.lo; - let cond = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL); + let cond = self.parse_expr_res(RestrictionNoStructLiteral); let thn = self.parse_block(); let mut els: Option> = None; let mut hi = thn.span.hi; @@ -2791,7 +2788,7 @@ impl<'a> Parser<'a> { let lo = self.last_span.lo; let pat = self.parse_pat(); self.expect_keyword(keywords::In); - let expr = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL); + let expr = self.parse_expr_res(RestrictionNoStructLiteral); let loop_block = self.parse_block(); let hi = self.span.hi; @@ -2800,7 +2797,7 @@ impl<'a> Parser<'a> { pub fn parse_while_expr(&mut self, opt_ident: Option) -> P { let lo = self.last_span.lo; - let cond = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL); + let cond = self.parse_expr_res(RestrictionNoStructLiteral); let body = self.parse_block(); let hi = body.span.hi; return self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident)); @@ -2815,7 +2812,7 @@ impl<'a> Parser<'a> { fn parse_match_expr(&mut self) -> P { let lo = self.last_span.lo; - let discriminant = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL); + let discriminant = self.parse_expr_res(RestrictionNoStructLiteral); self.commit_expr_expecting(&*discriminant, token::LBRACE); let mut arms: Vec = Vec::new(); while self.token != token::RBRACE { @@ -2834,7 +2831,7 @@ impl<'a> Parser<'a> { guard = Some(self.parse_expr()); } self.expect(&token::FAT_ARROW); - let expr = self.parse_expr_res(RESTRICT_STMT_EXPR); + let expr = self.parse_expr_res(RestrictionStmtExpr); let require_comma = !classify::expr_is_simple_block(&*expr) @@ -2856,15 +2853,15 @@ impl<'a> Parser<'a> { /// Parse an expression pub fn parse_expr(&mut self) -> P { - return self.parse_expr_res(UNRESTRICTED); + return self.parse_expr_res(Unrestricted); } - /// Parse an expression, subject to the given restriction - pub fn parse_expr_res(&mut self, r: restriction) -> P { - let old = self.restriction; - self.restriction = r; + /// Parse an expression, subject to the given restrictions + pub fn parse_expr_res(&mut self, r: Restrictions) -> P { + let old = self.restrictions; + self.restrictions = r; let e = self.parse_assign_expr(); - self.restriction = old; + self.restrictions = old; return e; } @@ -3153,9 +3150,9 @@ impl<'a> Parser<'a> { self.look_ahead(2, |t| { *t != token::COMMA && *t != token::RBRACKET }) { - let start = self.parse_expr_res(RESTRICT_NO_BAR_OP); + let start = self.parse_expr_res(RestrictionNoBarOp); self.eat(&token::DOTDOT); - let end = self.parse_expr_res(RESTRICT_NO_BAR_OP); + let end = self.parse_expr_res(RestrictionNoBarOp); pat = PatRange(start, end); } else if is_plain_ident(&self.token) && !can_be_enum_or_struct { let id = self.parse_ident(); @@ -3441,7 +3438,7 @@ impl<'a> Parser<'a> { check_expected_item(self, found_attrs); // Remainder are line-expr stmts. - let e = self.parse_expr_res(RESTRICT_STMT_EXPR); + let e = self.parse_expr_res(RestrictionStmtExpr); P(spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID))) } } @@ -3450,7 +3447,7 @@ impl<'a> Parser<'a> { /// Is this expression a successfully-parsed statement? fn expr_is_complete(&mut self, e: &Expr) -> bool { - self.restriction == RESTRICT_STMT_EXPR && + self.restrictions.contains(RestrictionStmtExpr) && !classify::expr_requires_semi_to_be_stmt(e) } diff --git a/src/snapshots.txt b/src/snapshots.txt index d2a1fd11597..86fa0a51f90 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,12 @@ +S 2014-09-16 828e075 + winnt-x86_64 ce1e9d7f6967bfa368853e7c968e1626cc319951 + winnt-i386 a8bd994666dfe683a5d7922c7998500255780724 + linux-x86_64 88ff474db96c6ffc5c1dc7a43442cbe1cd88c8a2 + linux-i386 7a731891f726c8a0590b142a4e8924c5e8b22e8d + freebsd-x86_64 e67a56f76484f775cd4836dedb2d1069ab5d7921 + macos-i386 f48023648a77e89086f4a2b39d76b09e4fff032d + macos-x86_64 2ad6457b2b3036f87eae7581d64ee5341a07fb06 + S 2014-09-10 6faa4f3 winnt-x86_64 939eb546469cb936441cff3b6f2478f562f77c46 winnt-i386 cfe4f8b519bb9d62588f9310a8f94bc919d5423b diff --git a/src/test/auxiliary/static_priv_by_default.rs b/src/test/auxiliary/static_priv_by_default.rs index b756eb2b582..6951ed729b2 100644 --- a/src/test/auxiliary/static_priv_by_default.rs +++ b/src/test/auxiliary/static_priv_by_default.rs @@ -24,6 +24,7 @@ mod foo { pub fn b() {} pub struct c; pub enum d {} + pub type e = int; pub struct A(()); @@ -36,6 +37,7 @@ mod foo { pub fn reexported_b() {} pub struct reexported_c; pub enum reexported_d {} + pub type reexported_e = int; } pub mod bar { @@ -43,14 +45,17 @@ pub mod bar { pub use foo::reexported_b as f; pub use foo::reexported_c as g; pub use foo::reexported_d as h; + pub use foo::reexported_e as i; } pub static a: int = 0; pub fn b() {} pub struct c; pub enum d {} +pub type e = int; -static i: int = 0; -fn j() {} -struct k; -enum l {} +static j: int = 0; +fn k() {} +struct l; +enum m {} +type n = int; diff --git a/src/test/bench/shootout-pidigits.rs b/src/test/bench/shootout-pidigits.rs deleted file mode 100644 index d22633b3412..00000000000 --- a/src/test/bench/shootout-pidigits.rs +++ /dev/null @@ -1,128 +0,0 @@ -// The Computer Language Benchmarks Game -// http://benchmarksgame.alioth.debian.org/ -// -// contributed by the Rust Project Developers - -// Copyright (c) 2013-2014 The Rust Project Developers -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// - Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// -// - Neither the name of "The Computer Language Benchmarks Game" nor -// the name of "The Computer Language Shootout Benchmarks" nor the -// names of its contributors may be used to endorse or promote -// products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -extern crate num; - -use std::from_str::FromStr; -use std::num::One; -use std::num::Zero; -use std::num::FromPrimitive; -use num::Integer; -use num::bigint::BigInt; - -struct Context { - numer: BigInt, - accum: BigInt, - denom: BigInt, -} - -impl Context { - fn new() -> Context { - Context { - numer: One::one(), - accum: Zero::zero(), - denom: One::one(), - } - } - - fn from_int(i: int) -> BigInt { - FromPrimitive::from_int(i).unwrap() - } - - fn extract_digit(&self) -> int { - if self.numer > self.accum {return -1;} - let (q, r) = - (self.numer * Context::from_int(3) + self.accum) - .div_rem(&self.denom); - if r + self.numer >= self.denom {return -1;} - q.to_int().unwrap() - } - - fn next_term(&mut self, k: int) { - let y2 = Context::from_int(k * 2 + 1); - self.accum = (self.accum + (self.numer << 1)) * y2; - self.numer = self.numer * Context::from_int(k); - self.denom = self.denom * y2; - } - - fn eliminate_digit(&mut self, d: int) { - let d = Context::from_int(d); - let ten = Context::from_int(10); - self.accum = (self.accum - self.denom * d) * ten; - self.numer = self.numer * ten; - } -} - -fn pidigits(n: int) { - let mut k = 0; - let mut context = Context::new(); - - for i in range(1, n + 1) { - let mut d; - loop { - k += 1; - context.next_term(k); - d = context.extract_digit(); - if d != -1 {break;} - } - - print!("{}", d); - if i % 10 == 0 {print!("\t:{}\n", i);} - - context.eliminate_digit(d); - } - - let m = n % 10; - if m != 0 { - for _ in range(m, 10) { print!(" "); } - print!("\t:{}\n", n); - } -} - -fn main() { - let args = std::os::args(); - let args = args.as_slice(); - let n = if args.len() < 2 { - 512 - } else { - FromStr::from_str(args[1].as_slice()).unwrap() - }; - pidigits(n); -} diff --git a/src/test/compile-fail/array-not-vector.rs b/src/test/compile-fail/array-not-vector.rs new file mode 100644 index 00000000000..79d4ada41e8 --- /dev/null +++ b/src/test/compile-fail/array-not-vector.rs @@ -0,0 +1,16 @@ +// 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. + +fn main() { + let _x: int = [1i, 2, 3]; //~ ERROR expected int, found array + + let x: &[int] = &[1, 2, 3]; + let _y: &int = x; //~ ERROR expected int, found unsized array +} diff --git a/src/test/compile-fail/issue-17283.rs b/src/test/compile-fail/issue-17283.rs new file mode 100644 index 00000000000..122c1f08395 --- /dev/null +++ b/src/test/compile-fail/issue-17283.rs @@ -0,0 +1,37 @@ +// 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. + +// Test that the parser does not attempt to parse struct literals +// within assignments in if expressions. + +struct Foo { + foo: uint +} + +fn main() { + let x = 1u; + let y: Foo; + + // `x { ... }` should not be interpreted as a struct literal here + if x = x { + //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ()) + println!("{}", x); + } + // Explicit parentheses on the left should match behavior of above + if (x = x) { + //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ()) + println!("{}", x); + } + // The struct literal interpretation is fine with explicit parentheses on the right + if y = (Foo { foo: x }) { + //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ()) + println!("{}", x); + } +} diff --git a/src/test/compile-fail/lint-unnecessary-import-braces.rs b/src/test/compile-fail/lint-unnecessary-import-braces.rs new file mode 100644 index 00000000000..c44918d9879 --- /dev/null +++ b/src/test/compile-fail/lint-unnecessary-import-braces.rs @@ -0,0 +1,21 @@ +// 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. + +#![deny(unnecessary_import_braces)] +#![allow(dead_code)] +#![allow(unused_imports)] + +use test::{A}; //~ ERROR braces around A is unnecessary + +mod test { + pub struct A; +} + +fn main() {} diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index 68dbacaae5c..41a30e23b22 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -82,5 +82,23 @@ fn f4b() -> int { } } +fn f5a() { + for x in range(1i, 10) { } + //~^ ERROR unused variable: `x` +} + +fn f5b() { + for (x, _) in [1i, 2, 3].iter().enumerate() { } + //~^ ERROR unused variable: `x` +} + +fn f5c() { + for (_, x) in [1i, 2, 3].iter().enumerate() { + //~^ ERROR unused variable: `x` + continue; + std::os::set_exit_status(*x); //~ WARNING unreachable statement + } +} + fn main() { } diff --git a/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs b/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs index 40cff3e466b..6b3c92e0028 100644 --- a/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs +++ b/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs @@ -35,10 +35,10 @@ fn test< 'a, 'b, A:IsStatic, - B:Is<'a>+Is2<'b>, //~ ERROR ambiguous lifetime bound + B:Is<'a>+Is2<'b>, // OK in a parameter, but not an object type. C:'b+Is<'a>+Is2<'b>, D:Is<'a>+Is2<'static>, - E:'a+'b //~ ERROR only a single explicit lifetime bound is permitted + E:'a+'b // OK in a parameter, but not an object type. >() { } fn main() { } diff --git a/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs b/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs new file mode 100644 index 00000000000..cec785c6e96 --- /dev/null +++ b/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs @@ -0,0 +1,32 @@ +// 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. + +// Various tests where we over type parameters with multiple lifetime +// bounds. + +trait SomeTrait { fn get(&self) -> int; } + +fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box { + // A outlives 'a AND 'b... + box v as Box // ...hence this type is safe. +} + +fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box { + // A outlives 'a AND 'b... + box v as Box // ...hence this type is safe. +} + +fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { + // A outlives 'a AND 'b...but not 'c. + box v as Box //~ ERROR mismatched types +} + +fn main() { +} diff --git a/src/test/compile-fail/xcrate-private-by-default.rs b/src/test/compile-fail/xcrate-private-by-default.rs index 70b2ea87ac1..43be96965d0 100644 --- a/src/test/compile-fail/xcrate-private-by-default.rs +++ b/src/test/compile-fail/xcrate-private-by-default.rs @@ -20,22 +20,26 @@ fn main() { static_priv_by_default::b; static_priv_by_default::c; foo::(); + foo::(); // publicly re-exported items should be available static_priv_by_default::bar::e; static_priv_by_default::bar::f; static_priv_by_default::bar::g; foo::(); + foo::(); // private items at the top should be inaccessible - static_priv_by_default::i; - //~^ ERROR: static `i` is private static_priv_by_default::j; - //~^ ERROR: function `j` is private + //~^ ERROR: static `j` is private static_priv_by_default::k; - //~^ ERROR: struct `k` is private - foo::(); - //~^ ERROR: type `l` is private + //~^ ERROR: function `k` is private + static_priv_by_default::l; + //~^ ERROR: struct `l` is private + foo::(); + //~^ ERROR: enum `m` is private + foo::(); + //~^ ERROR: type `n` is private // public items in a private mod should be inaccessible static_priv_by_default::foo::a; @@ -45,5 +49,7 @@ fn main() { static_priv_by_default::foo::c; //~^ ERROR: struct `c` is private foo::(); - //~^ ERROR: type `d` is private + //~^ ERROR: enum `d` is private + foo::(); + //~^ ERROR: type `e` is private } diff --git a/src/test/run-pass/issue-17302.rs b/src/test/run-pass/issue-17302.rs new file mode 100644 index 00000000000..50583c7d127 --- /dev/null +++ b/src/test/run-pass/issue-17302.rs @@ -0,0 +1,34 @@ +// 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. + +static mut DROPPED: [bool, ..2] = [false, false]; + +struct A(uint); +struct Foo { _a: A, _b: int } + +impl Drop for A { + fn drop(&mut self) { + let A(i) = *self; + unsafe { DROPPED[i] = true; } + } +} + +fn main() { + { + Foo { + _a: A(0), + ..Foo { _a: A(1), _b: 2 } + }; + } + unsafe { + assert!(DROPPED[0]); + assert!(DROPPED[1]); + } +} diff --git a/src/test/run-pass/regions-close-over-type-parameter-successfully.rs b/src/test/run-pass/regions-close-over-type-parameter-successfully.rs new file mode 100644 index 00000000000..5dba80ad38a --- /dev/null +++ b/src/test/run-pass/regions-close-over-type-parameter-successfully.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. + +// A test where we (successfully) close over a reference into +// an object. + +trait SomeTrait { fn get(&self) -> int; } + +impl<'a> SomeTrait for &'a int { + fn get(&self) -> int { + **self + } +} + +fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box { + box v as Box +} + +fn main() { + let i: int = 22; + let obj = make_object(&i); + assert_eq!(22, obj.get()); +}