diff --git a/COMPILER_TESTS.md b/COMPILER_TESTS.md index e4acf230e7211..546164c1492aa 100644 --- a/COMPILER_TESTS.md +++ b/COMPILER_TESTS.md @@ -1,6 +1,6 @@ # Compiler Test Documentation -In the Rust project, we use a special set of comands imbedded in +In the Rust project, we use a special set of comands embedded in comments to test the Rust compiler. There are two groups of commands: 1. Header commands @@ -29,11 +29,11 @@ The error levels that you can have are: 3. `NOTE` 4. `HELP` and `SUGGESTION`* -\* **Note**: `SUGGESTION` must follow emediatly after `HELP`. +\* **Note**: `SUGGESTION` must follow immediately after `HELP`. ## Summary of Header Commands -Header commands specify something about the entire test file, as a +Header commands specify something about the entire test file as a whole, instead of just a few lines inside the test. * `ignore-X` where `X` is an architecture, OS or stage will ignore the test accordingly diff --git a/Makefile.in b/Makefile.in index 8968fabf1b4b3..baa7e77394a0d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -26,7 +26,7 @@ # # * check - Run the complete test suite # -# * clean - Clean the build repertory. It is advised to run this +# * clean - Clean the build repository. It is advised to run this # command if you want to build Rust again, after an update # of the git repository. # diff --git a/RELEASES.md b/RELEASES.md index e8ce773ceff81..9b61ce0e05414 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,4 +1,4 @@ -Version 1.3.0 (September 2015) +Version 1.3.0 (2015-09-17) ============================== * ~900 changes, numerous bugfixes @@ -142,7 +142,7 @@ Misc [`Error`]: http://doc.rust-lang.org/nightly/std/error/trait.Error.html [`File`]: http://doc.rust-lang.org/nightly/std/fs/struct.File.html [`Hash`]: http://doc.rust-lang.org/nightly/std/hash/trait.Hash.html -[`Hasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.Hash.html +[`Hasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.Hasher.html [`Send`]: http://doc.rust-lang.org/nightly/std/marker/trait.Send.html [`SliceConcatExt`]: http://doc.rust-lang.org/nightly/std/slice/trait.SliceConcatExt.html [`Stdin`]: http://doc.rust-lang.org/nightly/std/io/struct.Stdin.html diff --git a/configure b/configure index 2d03b5f6f41ea..1d95965150cae 100755 --- a/configure +++ b/configure @@ -1095,6 +1095,12 @@ envopt CPP envopt CFLAGS envopt CXXFLAGS +# stdc++ name in use +# used to manage non-standard name (on OpenBSD for example) +program_transform_name=$($CFG_CC -v 2>&1 | sed -n "s/.*--program-transform-name='\([^']*\)'.*/\1/p") +CFG_STDCPP_NAME=$(echo "stdc++" | sed "${program_transform_name}") +putvar CFG_STDCPP_NAME + # a little post-processing of various config values CFG_PREFIX=${CFG_PREFIX%/} CFG_MANDIR=${CFG_MANDIR%/} diff --git a/mk/llvm.mk b/mk/llvm.mk index d5b608e88daf8..1cbf4a9fb841c 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -73,7 +73,7 @@ $$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1) LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \ - -print-file-name=libstdc++.a))" + -print-file-name=lib$(CFG_STDCPP_NAME).a))" else LLVM_STDCPP_RUSTFLAGS_$(1) = endif @@ -83,7 +83,7 @@ endif LLVM_LINKAGE_PATH_$(1):=$$(abspath $$(RT_OUTPUT_DIR_$(1))/llvmdeps.rs) $$(LLVM_LINKAGE_PATH_$(1)): $(S)src/etc/mklldeps.py $$(LLVM_CONFIG_$(1)) $(Q)$(CFG_PYTHON) "$$<" "$$@" "$$(LLVM_COMPONENTS)" "$$(CFG_ENABLE_LLVM_STATIC_STDCPP)" \ - $$(LLVM_CONFIG_$(1)) + $$(LLVM_CONFIG_$(1)) "$(CFG_STDCPP_NAME)" endef $(foreach host,$(CFG_HOST), \ diff --git a/mk/tests.mk b/mk/tests.mk index e0984cfe86f07..d004558d1bf3f 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -1046,6 +1046,10 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),rmake): \ $$(RMAKE_TESTS:%=$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok) @touch $$@ +$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ + export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(3))) +$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ + export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(3))) $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ $(S)src/test/run-make/%/Makefile \ $$(CSREQ$(1)_T_$(2)_H_$(3)) @@ -1056,7 +1060,7 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ $$(MAKE) \ $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ $(3)/test/run-make/$$* \ - $$(CC_$(3)) \ + '$$(CC_$(3))' \ "$$(CFG_GCCISH_CFLAGS_$(3))" \ $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \ "$$(TESTNAME)" \ @@ -1064,7 +1068,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ "$$(LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3))" \ "$$(LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3))" \ $(1) \ - $$(S) + $$(S) \ + $(3) @touch -r $$@.start_time $$@ && rm $$@.start_time else # FIXME #11094 - The above rule doesn't work right for multiple targets diff --git a/src/doc/reference.md b/src/doc/reference.md index 717c99901d1bc..83849574260e1 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1178,11 +1178,22 @@ let px: i32 = match p { Point(x, _) => x }; ``` A _unit-like struct_ is a structure without any fields, defined by leaving off -the list of fields entirely. Such types will have a single value. For example: +the list of fields entirely. Such a structure implicitly defines a constant of +its type with the same name. For example: ``` +# #![feature(braced_empty_structs)] struct Cookie; -let c = [Cookie, Cookie, Cookie, Cookie]; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; +``` + +is equivalent to + +``` +# #![feature(braced_empty_structs)] +struct Cookie {} +const Cookie: Cookie = Cookie {}; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; ``` The precise memory layout of a structure is not specified. One can specify a @@ -2411,6 +2422,7 @@ The currently implemented features of the reference compiler are: terms of encapsulation). * - `default_type_parameter_fallback` - Allows type parameter defaults to influence type inference. +* - `braced_empty_structs` - Allows use of empty structs with braces. If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about `#![feature]` directives which enabled @@ -2762,7 +2774,7 @@ The following expressions are equivalent. let x = std::ops::Range {start: 0, end: 10}; let y = 0..10; -assert_eq!(x,y); +assert_eq!(x, y); ``` ### Unary operator expressions @@ -3035,10 +3047,10 @@ A `loop` expression may optionally have a _label_. The label is written as a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a label is present, then labeled `break` and `continue` expressions nested within this loop may exit out of this loop or return control to its head. -See [Break expressions](#break-expressions) and [Continue +See [break expressions](#break-expressions) and [continue expressions](#continue-expressions). -### Break expressions +### `break` expressions A `break` expression has an optional _label_. If the label is absent, then executing a `break` expression immediately terminates the innermost loop @@ -3046,7 +3058,7 @@ enclosing it. It is only permitted in the body of a loop. If the label is present, then `break 'foo` terminates the loop with label `'foo`, which need not be the innermost label enclosing the `break` expression, but must enclose it. -### Continue expressions +### `continue` expressions A `continue` expression has an optional _label_. If the label is absent, then executing a `continue` expression immediately terminates the current iteration @@ -3059,7 +3071,7 @@ innermost label enclosing the `break` expression, but must enclose it. A `continue` expression is only permitted in the body of a loop. -### While loops +### `while` loops A `while` loop begins by evaluating the boolean loop conditional expression. If the loop conditional expression evaluates to `true`, the loop body block @@ -3082,12 +3094,12 @@ Like `loop` expressions, `while` loops can be controlled with `break` or loops](#infinite-loops), [break expressions](#break-expressions), and [continue expressions](#continue-expressions) for more information. -### For expressions +### `for` expressions A `for` expression is a syntactic construct for looping over elements provided by an implementation of `std::iter::IntoIterator`. -An example of a for loop over the contents of an array: +An example of a `for` loop over the contents of an array: ``` # type Foo = i32; @@ -3117,7 +3129,7 @@ Like `loop` expressions, `for` loops can be controlled with `break` or loops](#infinite-loops), [break expressions](#break-expressions), and [continue expressions](#continue-expressions) for more information. -### If expressions +### `if` expressions An `if` expression is a conditional branch in program control. The form of an `if` expression is a condition expression, followed by a consequent block, any @@ -3129,7 +3141,7 @@ evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated. If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed. -### Match expressions +### `match` expressions A `match` expression branches on a *pattern*. The exact form of matching that occurs depends on the pattern. Patterns consist of some combination of @@ -3235,7 +3247,7 @@ let message = match maybe_digit { }; ``` -### If let expressions +### `if let` expressions An `if let` expression is semantically identical to an `if` expression but in place of a condition expression it expects a refutable let statement. If the value of the @@ -3256,7 +3268,7 @@ if let ("Ham", b) = dish { } ``` -### While let loops +### `while let` loops A `while let` loop is semantically identical to a `while` loop but in place of a condition expression it expects a refutable let statement. If the value of the @@ -3264,7 +3276,7 @@ expression on the right hand side of the let statement matches the pattern, the loop body block executes and control returns to the pattern matching statement. Otherwise, the while expression completes. -### Return expressions +### `return` expressions Return expressions are denoted with the keyword `return`. Evaluating a `return` expression moves its argument into the designated output location for the diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index e335d59b1929d..18ce93ea06a64 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -28,7 +28,7 @@ systems may want to jump around. * [The `Result` type](#the-result-type) * [Parsing integers](#parsing-integers) * [The `Result` type alias idiom](#the-result-type-alias-idiom) - * [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil) + * [A brief interlude: unwrapping isn't evil](#a-brief-interlude:-unwrapping-isn't-evil) * [Working with multiple error types](#working-with-multiple-error-types) * [Composing `Option` and `Result`](#composing-option-and-result) * [The limits of combinators](#the-limits-of-combinators) @@ -41,11 +41,11 @@ systems may want to jump around. * [The real `try!` macro](#the-real-try!-macro) * [Composing custom error types](#composing-custom-error-types) * [Advice for library writers](#advice-for-library-writers) -* [Case study: A program to read population data](#case-study-a-program-to-read-population-data) +* [Case study: A program to read population data](#case-study:-a-program-to-read-population-data) * [Initial setup](#initial-setup) * [Argument parsing](#argument-parsing) * [Writing the logic](#writing-the-logic) - * [Error handling with `Box`](#error-handling-with-box) + * [Error handling with `Box`](#error-handling-with-box%3Cerror%3E) * [Reading from stdin](#reading-from-stdin) * [Error handling with a custom type](#error-handling-with-a-custom-type) * [Adding functionality](#adding-functionality) @@ -87,6 +87,8 @@ thread '
' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5 Here's another example that is slightly less contrived. A program that accepts an integer as an argument, doubles it and prints it. + + ```rust,should_panic use std::env; @@ -120,7 +122,7 @@ It would be better if we just showed the code for unwrapping because it is so simple, but to do that, we will first need to explore the `Option` and `Result` types. Both of these types have a method called `unwrap` defined on them. -## The `Option` type +### The `Option` type The `Option` type is [defined in the standard library][5]: @@ -137,6 +139,8 @@ system is an important concept because it will cause the compiler to force the programmer to handle that absence. Let's take a look at an example that tries to find a character in a string: + + ```rust // Searches `haystack` for the Unicode character `needle`. If one is found, the // byte offset of the character is returned. Otherwise, `None` is returned. @@ -182,6 +186,8 @@ But wait, what about `unwrap` used in [`unwrap-double`](#code-unwrap-double)? There was no case analysis there! Instead, the case analysis was put inside the `unwrap` method for you. You could define it yourself if you want: + + ```rust enum Option { None, @@ -205,7 +211,7 @@ that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that ### Composing `Option` values -In [`option-ex-string-find`](#code-option-ex-string-find-2) +In [`option-ex-string-find`](#code-option-ex-string-find) we saw how to use `find` to discover the extension in a file name. Of course, not all file names have a `.` in them, so it's possible that the file name has no extension. This *possibility of absence* is encoded into the types using @@ -247,6 +253,8 @@ option is `None`, in which case, just return `None`. Rust has parametric polymorphism, so it is very easy to define a combinator that abstracts this pattern: + + ```rust fn map(option: Option, f: F) -> Option where F: FnOnce(T) -> A { match option { @@ -386,6 +394,8 @@ remove choices because they will panic if `Option` is `None`. The `Result` type is also [defined in the standard library][6]: + + ```rust enum Result { Ok(T), @@ -662,6 +672,8 @@ with both an `Option` and a `Result`, the solution is *usually* to convert the (from `env::args()`) means the user didn't invoke the program correctly. We could just use a `String` to describe the error. Let's try: + + ```rust use std::env; @@ -894,6 +906,8 @@ seen above. Here is a simplified definition of a `try!` macro: + + ```rust macro_rules! try { ($e:expr) => (match $e { @@ -1154,6 +1168,8 @@ The `std::convert::From` trait is [defined in the standard library](../std/convert/trait.From.html): + + ```rust trait From { fn from(T) -> Self; @@ -1231,9 +1247,11 @@ macro_rules! try { } ``` -This is not it's real definition. It's real definition is +This is not its real definition. Its real definition is [in the standard library](../std/macro.try!.html): + + ```rust macro_rules! try { ($e:expr) => (match $e { @@ -1452,7 +1470,7 @@ representation. But certainly, this will vary depending on use cases. At a minimum, you should probably implement the [`Error`](../std/error/trait.Error.html) trait. This will give users of your library some minimum flexibility for -[composing errors](#the-real-try-macro). Implementing the `Error` trait also +[composing errors](#the-real-try!-macro). Implementing the `Error` trait also means that users are guaranteed the ability to obtain a string representation of an error (because it requires impls for both `fmt::Debug` and `fmt::Display`). diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index 4a35022b03c91..94280aa4a3317 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -147,7 +147,7 @@ a few tricks up their sleeves. For example, they’re [immutable][immutable] by default. That’s why our example uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t -take a name on the left hand side, it actually accepts a +take a name on the left hand side of the assignment, it actually accepts a ‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough to use for now: @@ -599,7 +599,7 @@ With this definition, anything of type `Foo` can be either a `Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the namespace for a particular `enum` variant. -The [`Ordering`][ordering] enum has three possible variants: `Less`, `Equal`, +The [`Ordering`][ordering] `enum` has three possible variants: `Less`, `Equal`, and `Greater`. The `match` statement takes a value of a type, and lets you create an ‘arm’ for each possible value. Since we have three types of `Ordering`, we have three arms: @@ -918,9 +918,9 @@ let guess: u32 = match guess.trim().parse() { This is how you generally move from ‘crash on error’ to ‘actually handle the error’, by switching from `ok().expect()` to a `match` statement. The `Result` -returned by `parse()` is an enum just like `Ordering`, but in this case, each +returned by `parse()` is an `enum` just like `Ordering`, but in this case, each variant has some data associated with it: `Ok` is a success, and `Err` is a -failure. Each contains more information: the successful parsed integer, or an +failure. Each contains more information: the successfully parsed integer, or an error type. In this case, we `match` on `Ok(num)`, which sets the inner value of the `Ok` to the name `num`, and then we just return it on the right-hand side. In the `Err` case, we don’t care what kind of error it is, so we just diff --git a/src/doc/trpl/installing-rust.md b/src/doc/trpl/installing-rust.md index f06005d55b961..366069ac9a3bf 100644 --- a/src/doc/trpl/installing-rust.md +++ b/src/doc/trpl/installing-rust.md @@ -64,7 +64,7 @@ Oh, we should also mention the officially supported platforms: * Windows (7, 8, Server 2008 R2) * Linux (2.6.18 or later, various distributions), x86 and x86-64 -* OSX 10.7 (Lion) or greater, x86 and x86-64 +* OSX 10.7 (Lion) or later, x86 and x86-64 We extensively test Rust on these platforms, and a few others, too, like Android. But these are the ones most likely to work, as they have the most diff --git a/src/doc/trpl/the-stack-and-the-heap.md b/src/doc/trpl/the-stack-and-the-heap.md index fb778b59a3d93..aca736ef2ac3b 100644 --- a/src/doc/trpl/the-stack-and-the-heap.md +++ b/src/doc/trpl/the-stack-and-the-heap.md @@ -217,18 +217,18 @@ on the heap. The actual value of the box is a structure which has a pointer to it allocates some memory for the heap, and puts `5` there. The memory now looks like this: -| Address | Name | Value | -|-----------------|------|------------------| -| 230 | | 5 | -| ... | ... | ... | -| 1 | y | 42 | -| 0 | x | → 230 | - -We have 230 in our hypothetical computer with 1GB of RAM. And since +| Address | Name | Value | +|----------------------|------|------------------------| +| (230) - 1 | | 5 | +| ... | ... | ... | +| 1 | y | 42 | +| 0 | x | → (230) - 1 | + +We have (230) - 1 in our hypothetical computer with 1GB of RAM. And since our stack grows from zero, the easiest place to allocate memory is from the other end. So our first value is at the highest place in memory. And the value of the struct at `x` has a [raw pointer][rawpointer] to the place we’ve -allocated on the heap, so the value of `x` is 230, the memory +allocated on the heap, so the value of `x` is (230) - 1, the memory location we’ve asked for. [rawpointer]: raw-pointers.html @@ -244,18 +244,18 @@ layout of a program which has been running for a while now: | Address | Name | Value | |----------------------|------|------------------------| -| 230 | | 5 | -| (230) - 1 | | | +| (230) - 1 | | 5 | | (230) - 2 | | | -| (230) - 3 | | 42 | +| (230) - 3 | | | +| (230) - 4 | | 42 | | ... | ... | ... | -| 3 | y | → (230) - 3 | +| 3 | y | → (230) - 4 | | 2 | y | 42 | | 1 | y | 42 | -| 0 | x | → 230 | +| 0 | x | → (230) - 1 | In this case, we’ve allocated four things on the heap, but deallocated two of -them. There’s a gap between 230 and (230) - 3 which isn’t +them. There’s a gap between (230) - 1 and (230) - 4 which isn’t currently being used. The specific details of how and why this happens depends on what kind of strategy you use to manage the heap. Different programs can use different ‘memory allocators’, which are libraries that manage this for you. @@ -366,29 +366,29 @@ fn main() { First, we call `main()`: -| Address | Name | Value | -|-----------------|------|------------------| -| 230 | | 20 | -| ... | ... | ... | -| 2 | j | → 0 | -| 1 | i | → 230 | -| 0 | h | 3 | +| Address | Name | Value | +|----------------------|------|------------------------| +| (230) - 1 | | 20 | +| ... | ... | ... | +| 2 | j | → 0 | +| 1 | i | → (230) - 1 | +| 0 | h | 3 | We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a value pointing there. Next, at the end of `main()`, `foo()` gets called: -| Address | Name | Value | -|-----------------|------|-----------------| -| 230 | | 20 | -| ... | ... | ... | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → 230| -| 0 | h | 3 | +| Address | Name | Value | +|----------------------|------|------------------------| +| (230) - 1 | | 20 | +| ... | ... | ... | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → (230) - 1 | +| 0 | h | 3 | Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value as `j`, since that’s what we passed it in. It’s a pointer to the `0` address, @@ -396,42 +396,42 @@ since `j` points at `h`. Next, `foo()` calls `baz()`, passing `z`: -| Address | Name | Value | -|-----------------|------|------------------| -| 230 | | 20 | -| ... | ... | ... | -| 7 | g | 100 | -| 6 | f | → 4 | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → 230 | -| 0 | h | 3 | +| Address | Name | Value | +|----------------------|------|------------------------| +| (230) - 1 | | 20 | +| ... | ... | ... | +| 7 | g | 100 | +| 6 | f | → 4 | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → (230) - 1 | +| 0 | h | 3 | We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s over, we get rid of its stack frame: -| Address | Name | Value | -|-----------------|------|------------------| -| 230 | | 20 | -| ... | ... | ... | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → 230 | -| 0 | h | 3 | +| Address | Name | Value | +|----------------------|------|------------------------| +| (230) - 1 | | 20 | +| ... | ... | ... | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → (230) - 1 | +| 0 | h | 3 | Next, `foo()` calls `bar()` with `x` and `z`: | Address | Name | Value | |----------------------|------|------------------------| -| 230 | | 20 | -| (230) - 1 | | 5 | +| (230) - 1 | | 20 | +| (230) - 2 | | 5 | | ... | ... | ... | | 10 | e | → 9 | -| 9 | d | → (230) - 1 | +| 9 | d | → (230) - 2 | | 8 | c | 5 | | 7 | b | → 4 | | 6 | a | → 0 | @@ -439,24 +439,24 @@ Next, `foo()` calls `bar()` with `x` and `z`: | 4 | y | 10 | | 3 | x | → 0 | | 2 | j | → 0 | -| 1 | i | → 230 | +| 1 | i | → (230) - 1 | | 0 | h | 3 | We end up allocating another value on the heap, and so we have to subtract one -from 230. It’s easier to just write that than `1,073,741,823`. In any +from (230) - 1. It’s easier to just write that than `1,073,741,822`. In any case, we set up the variables as usual. At the end of `bar()`, it calls `baz()`: | Address | Name | Value | |----------------------|------|------------------------| -| 230 | | 20 | -| (230) - 1 | | 5 | +| (230) - 1 | | 20 | +| (230) - 2 | | 5 | | ... | ... | ... | | 12 | g | 100 | | 11 | f | → 9 | | 10 | e | → 9 | -| 9 | d | → (230) - 1 | +| 9 | d | → (230) - 2 | | 8 | c | 5 | | 7 | b | → 4 | | 6 | a | → 0 | @@ -464,7 +464,7 @@ At the end of `bar()`, it calls `baz()`: | 4 | y | 10 | | 3 | x | → 0 | | 2 | j | → 0 | -| 1 | i | → 230 | +| 1 | i | → (230) - 1 | | 0 | h | 3 | With this, we’re at our deepest point! Whew! Congrats for following along this @@ -474,11 +474,11 @@ After `baz()` is over, we get rid of `f` and `g`: | Address | Name | Value | |----------------------|------|------------------------| -| 230 | | 20 | -| (230) - 1 | | 5 | +| (230) - 1 | | 20 | +| (230) - 2 | | 5 | | ... | ... | ... | | 10 | e | → 9 | -| 9 | d | → (230) - 1 | +| 9 | d | → (230) - 2 | | 8 | c | 5 | | 7 | b | → 4 | | 6 | a | → 0 | @@ -486,32 +486,32 @@ After `baz()` is over, we get rid of `f` and `g`: | 4 | y | 10 | | 3 | x | → 0 | | 2 | j | → 0 | -| 1 | i | → 230 | +| 1 | i | → (230) - 1 | | 0 | h | 3 | Next, we return from `bar()`. `d` in this case is a `Box`, so it also frees -what it points to: (230) - 1. - -| Address | Name | Value | -|-----------------|------|------------------| -| 230 | | 20 | -| ... | ... | ... | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → 230 | -| 0 | h | 3 | +what it points to: (230) - 2. + +| Address | Name | Value | +|----------------------|------|------------------------| +| (230) - 1 | | 20 | +| ... | ... | ... | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → (230) - 1 | +| 0 | h | 3 | And after that, `foo()` returns: -| Address | Name | Value | -|-----------------|------|------------------| -| 230 | | 20 | -| ... | ... | ... | -| 2 | j | → 0 | -| 1 | i | → 230 | -| 0 | h | 3 | +| Address | Name | Value | +|----------------------|------|------------------------| +| (230) - 1 | | 20 | +| ... | ... | ... | +| 2 | j | → 0 | +| 1 | i | → (230) - 1 | +| 0 | h | 3 | And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped, it will clean up the last of the heap too. diff --git a/src/etc/maketest.py b/src/etc/maketest.py index 04bf81a96aaf3..c2958caddc400 100644 --- a/src/etc/maketest.py +++ b/src/etc/maketest.py @@ -12,6 +12,7 @@ import os import sys +target_triple = sys.argv[14] def normalize_path(v): """msys1/msys2 automatically converts `/abs/path1:/abs/path2` into @@ -22,8 +23,11 @@ def normalize_path(v): windows paths so it is really error-prone. revert it for peace.""" v = v.replace('\\', '/') # c:/path -> /c/path - if ':/' in v: - v = '/' + v.replace(':/', '/') + # "c:/path" -> "/c/path" + start = v.find(':/') + while start != -1: + v = v[:start - 1] + '/' + v[start - 1:start] + v[start + 1:] + start = v.find(':/') return v @@ -50,6 +54,10 @@ def convert_path_spec(name, value): putenv('RUST_BUILD_STAGE', sys.argv[12]) putenv('S', os.path.abspath(sys.argv[13])) putenv('PYTHON', sys.executable) +os.putenv('TARGET', target_triple) + +if 'msvc' in target_triple: + os.putenv('IS_MSVC', '1') if filt not in sys.argv[1]: sys.exit(0) diff --git a/src/etc/mklldeps.py b/src/etc/mklldeps.py index 1cc65406b2c00..215fa1cdd1bb7 100644 --- a/src/etc/mklldeps.py +++ b/src/etc/mklldeps.py @@ -17,6 +17,7 @@ components = sys.argv[2].split() # splits on whitespace enable_static = sys.argv[3] llvm_config = sys.argv[4] +stdcpp_name = sys.argv[5] f.write("""// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at @@ -77,7 +78,7 @@ def run(args): out = run([llvm_config, '--cxxflags']) if enable_static == '1': assert('stdlib=libc++' not in out) - f.write("#[link(name = \"stdc++\", kind = \"static\")]\n") + f.write("#[link(name = \"" + stdcpp_name + "\", kind = \"static\")]\n") else: # Note that we use `cfg_attr` here because on MSVC the C++ standard library # is not c++ or stdc++, but rather the linker takes care of linking the @@ -85,7 +86,7 @@ def run(args): if 'stdlib=libc++' in out: f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"c++\"))]\n") else: - f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"stdc++\"))]\n") + f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"" + stdcpp_name + "\"))]\n") # Attach everything to an extern block f.write("extern {}\n") diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index aea5feb4be1ff..3344d7ea5d7fc 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -463,17 +463,33 @@ mod impls { } } - partial_ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } + partial_ord_impl! { f32 f64 } macro_rules! ord_impl { ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialOrd for $t { + #[inline] + fn partial_cmp(&self, other: &$t) -> Option { + Some(self.cmp(other)) + } + #[inline] + fn lt(&self, other: &$t) -> bool { (*self) < (*other) } + #[inline] + fn le(&self, other: &$t) -> bool { (*self) <= (*other) } + #[inline] + fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } + #[inline] + fn gt(&self, other: &$t) -> bool { (*self) > (*other) } + } + #[stable(feature = "rust1", since = "1.0.0")] impl Ord for $t { #[inline] fn cmp(&self, other: &$t) -> Ordering { - if *self < *other { Less } - else if *self > *other { Greater } - else { Equal } + if *self == *other { Equal } + else if *self < *other { Less } + else { Greater } } } )*) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 07de4d0761baa..5f0eb63edbc45 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -94,7 +94,7 @@ use fmt; #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Drop { - /// The `drop` method, called when the value goes out of scope. + /// A method called when the value goes out of scope. #[stable(feature = "rust1", since = "1.0.0")] fn drop(&mut self); } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a539ef81db89c..d1bb65d22904a 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -541,7 +541,7 @@ impl Option { /// ``` /// let mut x = Some(4); /// match x.iter_mut().next() { - /// Some(&mut ref mut v) => *v = 42, + /// Some(v) => *v = 42, /// None => {}, /// } /// assert_eq!(x, Some(42)); diff --git a/src/libcore/result.rs b/src/libcore/result.rs index e9a67196751e0..fe0fdb5baa5f3 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -538,7 +538,7 @@ impl Result { /// ``` /// let mut x: Result = Ok(7); /// match x.iter_mut().next() { - /// Some(&mut ref mut x) => *x = 40, + /// Some(v) => *v = 40, /// None => {}, /// } /// assert_eq!(x, Ok(40)); diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 8d3d798afef13..5518bacb019e8 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1559,30 +1559,41 @@ impl Eq for [T] {} #[stable(feature = "rust1", since = "1.0.0")] impl Ord for [T] { fn cmp(&self, other: &[T]) -> Ordering { - self.iter().cmp(other.iter()) + let l = cmp::min(self.len(), other.len()); + + // Slice to the loop iteration range to enable bound check + // elimination in the compiler + let lhs = &self[..l]; + let rhs = &other[..l]; + + for i in 0..l { + match lhs[i].cmp(&rhs[i]) { + Ordering::Equal => (), + non_eq => return non_eq, + } + } + + self.len().cmp(&other.len()) } } #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for [T] { - #[inline] fn partial_cmp(&self, other: &[T]) -> Option { - self.iter().partial_cmp(other.iter()) - } - #[inline] - fn lt(&self, other: &[T]) -> bool { - self.iter().lt(other.iter()) - } - #[inline] - fn le(&self, other: &[T]) -> bool { - self.iter().le(other.iter()) - } - #[inline] - fn ge(&self, other: &[T]) -> bool { - self.iter().ge(other.iter()) - } - #[inline] - fn gt(&self, other: &[T]) -> bool { - self.iter().gt(other.iter()) + let l = cmp::min(self.len(), other.len()); + + // Slice to the loop iteration range to enable bound check + // elimination in the compiler + let lhs = &self[..l]; + let rhs = &other[..l]; + + for i in 0..l { + match lhs[i].partial_cmp(&rhs[i]) { + Some(Ordering::Equal) => (), + non_eq => return non_eq, + } + } + + self.len().partial_cmp(&other.len()) } } diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 53952cdc9080b..0f72dcc1281a4 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -92,6 +92,7 @@ impl Default for AtomicBool { } } +// Send is implicitly implemented for AtomicBool. unsafe impl Sync for AtomicBool {} /// A signed integer type which can be safely shared between threads. @@ -106,6 +107,7 @@ impl Default for AtomicIsize { } } +// Send is implicitly implemented for AtomicIsize. unsafe impl Sync for AtomicIsize {} /// An unsigned integer type which can be safely shared between threads. @@ -120,6 +122,7 @@ impl Default for AtomicUsize { } } +// Send is implicitly implemented for AtomicUsize. unsafe impl Sync for AtomicUsize {} /// A raw pointer type which can be safely shared between threads. diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 495044f945949..d9b05d804000a 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -14,7 +14,7 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -use lint::{LintPass, LintArray}; +use lint::{LintPass, LateLintPass, LintArray}; declare_lint! { pub UNUSED_IMPORTS, @@ -138,3 +138,5 @@ impl LintPass for HardwiredLints { ) } } + +impl LateLintPass for HardwiredLints {} diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index dade1f4eb26fa..9a736747d5291 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -28,7 +28,8 @@ use self::TargetLint::*; use middle::privacy::ExportedItems; use middle::ty::{self, Ty}; use session::{early_error, Session}; -use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass, LintPassObject}; +use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass}; +use lint::{EarlyLintPass, EarlyLintPassObject, LateLintPass, LateLintPassObject}; use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid}; use lint::builtin; use util::nodemap::FnvHashMap; @@ -36,15 +37,15 @@ use util::nodemap::FnvHashMap; use std::cell::RefCell; use std::cmp; use std::mem; -use syntax::ast_util::IdVisitingOperation; +use syntax::ast_util::{self, IdVisitingOperation}; use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::ast; use rustc_front::hir; -use rustc_front::visit::{self, Visitor, FnKind}; use rustc_front::util; -use syntax::visit::Visitor as SyntaxVisitor; +use rustc_front::visit as hir_visit; +use syntax::visit as ast_visit; use syntax::diagnostic; /// Information about the registered lints. @@ -59,7 +60,8 @@ pub struct LintStore { /// Trait objects for each lint pass. /// This is only `None` while iterating over the objects. See the definition /// of run_lints. - passes: Option>, + early_passes: Option>, + late_passes: Option>, /// Lints indexed by name. by_name: FnvHashMap, @@ -115,7 +117,8 @@ impl LintStore { pub fn new() -> LintStore { LintStore { lints: vec!(), - passes: Some(vec!()), + early_passes: Some(vec!()), + late_passes: Some(vec!()), by_name: FnvHashMap(), levels: FnvHashMap(), lint_groups: FnvHashMap(), @@ -133,8 +136,27 @@ impl LintStore { v.1)).collect() } - pub fn register_pass(&mut self, sess: Option<&Session>, - from_plugin: bool, pass: LintPassObject) { + pub fn register_early_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + pass: EarlyLintPassObject) { + self.push_pass(sess, from_plugin, &pass); + self.early_passes.as_mut().unwrap().push(pass); + } + + pub fn register_late_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + pass: LateLintPassObject) { + self.push_pass(sess, from_plugin, &pass); + self.late_passes.as_mut().unwrap().push(pass); + } + + // Helper method for register_early/late_pass + fn push_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + pass: &Box

) { for &lint in pass.get_lints() { self.lints.push((*lint, from_plugin)); @@ -156,7 +178,6 @@ impl LintStore { self.levels.insert(id, (lint.default_level, Default)); } } - self.passes.as_mut().unwrap().push(pass); } pub fn register_group(&mut self, sess: Option<&Session>, @@ -248,8 +269,8 @@ impl LintStore { } } -/// Context for lint checking. -pub struct Context<'a, 'tcx: 'a> { +/// Context for lint checking after type checking. +pub struct LateContext<'a, 'tcx: 'a> { /// Type context we're checking in. pub tcx: &'a ty::ctxt<'tcx>, @@ -272,15 +293,33 @@ pub struct Context<'a, 'tcx: 'a> { node_levels: RefCell>, } +/// Context for lint checking of the AST, after expansion, before lowering to +/// HIR. +pub struct EarlyContext<'a> { + /// Type context we're checking in. + pub sess: &'a Session, + + /// The crate being checked. + pub krate: &'a ast::Crate, + + /// The store of registered lints. + lints: LintStore, + + /// When recursing into an attributed node of the ast which modifies lint + /// levels, this stack keeps track of the previous lint levels of whatever + /// was modified. + level_stack: Vec<(LintId, LevelSource)>, +} + /// Convenience macro for calling a `LintPass` method on every pass in the context. -macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({ +macro_rules! run_lints { ($cx:expr, $f:ident, $ps:ident, $($args:expr),*) => ({ // Move the vector of passes out of `$cx` so that we can // iterate over it mutably while passing `$cx` to the methods. - let mut passes = $cx.lints.passes.take().unwrap(); + let mut passes = $cx.mut_lints().$ps.take().unwrap(); for obj in &mut passes { obj.$f($cx, $($args),*); } - $cx.lints.passes = Some(passes); + $cx.mut_lints().$ps = Some(passes); }) } /// Parse the lint attributes into a vector, with `Err`s for malformed lint @@ -364,65 +403,50 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint, } } -impl<'a, 'tcx> Context<'a, 'tcx> { - fn new(tcx: &'a ty::ctxt<'tcx>, - krate: &'a hir::Crate, - exported_items: &'a ExportedItems) -> Context<'a, 'tcx> { - // We want to own the lint store, so move it out of the session. - let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), - LintStore::new()); - - Context { - tcx: tcx, - krate: krate, - exported_items: exported_items, - lints: lint_store, - level_stack: vec![], - node_levels: RefCell::new(FnvHashMap()), - } - } - - /// Get the overall compiler `Session` object. - pub fn sess(&'a self) -> &'a Session { - &self.tcx.sess - } +pub trait LintContext: Sized { + fn sess(&self) -> &Session; + fn lints(&self) -> &LintStore; + fn mut_lints(&mut self) -> &mut LintStore; + fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)>; + fn enter_attrs(&mut self, attrs: &[ast::Attribute]); + fn exit_attrs(&mut self, attrs: &[ast::Attribute]); /// Get the level of `lint` at the current position of the lint /// traversal. - pub fn current_level(&self, lint: &'static Lint) -> Level { - self.lints.levels.get(&LintId::of(lint)).map_or(Allow, |&(lvl, _)| lvl) + fn current_level(&self, lint: &'static Lint) -> Level { + self.lints().levels.get(&LintId::of(lint)).map_or(Allow, |&(lvl, _)| lvl) } fn lookup_and_emit(&self, lint: &'static Lint, span: Option, msg: &str) { - let (level, src) = match self.lints.levels.get(&LintId::of(lint)) { + let (level, src) = match self.lints().levels.get(&LintId::of(lint)) { None => return, Some(&(Warn, src)) => { let lint_id = LintId::of(builtin::WARNINGS); - (self.lints.get_level_source(lint_id).0, src) + (self.lints().get_level_source(lint_id).0, src) } Some(&pair) => pair, }; - raw_emit_lint(&self.tcx.sess, lint, (level, src), span, msg); - } - - /// Emit a lint at the appropriate level, with no associated span. - pub fn lint(&self, lint: &'static Lint, msg: &str) { - self.lookup_and_emit(lint, None, msg); + raw_emit_lint(&self.sess(), lint, (level, src), span, msg); } /// Emit a lint at the appropriate level, for a particular span. - pub fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) { + fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) { self.lookup_and_emit(lint, Some(span), msg); } + /// Emit a lint at the appropriate level, with no associated span. + fn lint(&self, lint: &'static Lint, msg: &str) { + self.lookup_and_emit(lint, None, msg); + } + /// Merge the lints specified by any lint attributes into the /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. fn with_lint_attrs(&mut self, attrs: &[ast::Attribute], - f: F) where - F: FnOnce(&mut Context), + f: F) + where F: FnOnce(&mut Self), { // Parse all of the lint attributes, and then add them all to the // current dictionary of lint information. Along the way, keep a history @@ -433,15 +457,15 @@ impl<'a, 'tcx> Context<'a, 'tcx> { for result in gather_attrs(attrs) { let v = match result { Err(span) => { - span_err!(self.tcx.sess, span, E0452, + span_err!(self.sess(), span, E0452, "malformed lint attribute"); continue; } Ok((lint_name, level, span)) => { - match self.lints.find_lint(&lint_name, &self.tcx.sess, Some(span)) { + match self.lints().find_lint(&lint_name, &self.sess(), Some(span)) { Ok(lint_id) => vec![(lint_id, level, span)], Err(FindLintError::NotFound) => { - match self.lints.lint_groups.get(&lint_name[..]) { + match self.lints().lint_groups.get(&lint_name[..]) { Some(&(ref v, _)) => v.iter() .map(|lint_id: &LintId| (*lint_id, level, span)) @@ -460,35 +484,82 @@ impl<'a, 'tcx> Context<'a, 'tcx> { }; for (lint_id, level, span) in v { - let now = self.lints.get_level_source(lint_id).0; + let now = self.lints().get_level_source(lint_id).0; if now == Forbid && level != Forbid { let lint_name = lint_id.as_str(); - span_err!(self.tcx.sess, span, E0453, + span_err!(self.sess(), span, E0453, "{}({}) overruled by outer forbid({})", level.as_str(), lint_name, lint_name); } else if now != level { - let src = self.lints.get_level_source(lint_id).1; - self.level_stack.push((lint_id, (now, src))); + let src = self.lints().get_level_source(lint_id).1; + self.level_stack().push((lint_id, (now, src))); pushed += 1; - self.lints.set_level(lint_id, (level, Node(span))); + self.mut_lints().set_level(lint_id, (level, Node(span))); } } } - run_lints!(self, enter_lint_attrs, attrs); + self.enter_attrs(attrs); f(self); - run_lints!(self, exit_lint_attrs, attrs); + self.exit_attrs(attrs); // rollback for _ in 0..pushed { - let (lint, lvlsrc) = self.level_stack.pop().unwrap(); - self.lints.set_level(lint, lvlsrc); + let (lint, lvlsrc) = self.level_stack().pop().unwrap(); + self.mut_lints().set_level(lint, lvlsrc); + } + } +} + + +impl<'a> EarlyContext<'a> { + fn new(sess: &'a Session, + krate: &'a ast::Crate) -> EarlyContext<'a> { + // We want to own the lint store, so move it out of the session. Remember + // to put it back later... + let lint_store = mem::replace(&mut *sess.lint_store.borrow_mut(), + LintStore::new()); + EarlyContext { + sess: sess, + krate: krate, + lints: lint_store, + level_stack: vec![], + } + } + + fn visit_ids(&mut self, f: F) + where F: FnOnce(&mut ast_util::IdVisitor) + { + let mut v = ast_util::IdVisitor { + operation: self, + pass_through_items: false, + visited_outermost: false, + }; + f(&mut v); + } +} + +impl<'a, 'tcx> LateContext<'a, 'tcx> { + fn new(tcx: &'a ty::ctxt<'tcx>, + krate: &'a hir::Crate, + exported_items: &'a ExportedItems) -> LateContext<'a, 'tcx> { + // We want to own the lint store, so move it out of the session. + let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), + LintStore::new()); + + LateContext { + tcx: tcx, + krate: krate, + exported_items: exported_items, + lints: lint_store, + level_stack: vec![], + node_levels: RefCell::new(FnvHashMap()), } } - fn visit_ids(&mut self, f: F) where - F: FnOnce(&mut util::IdVisitor) + fn visit_ids(&mut self, f: F) + where F: FnOnce(&mut util::IdVisitor) { let mut v = util::IdVisitor { operation: self, @@ -499,41 +570,95 @@ impl<'a, 'tcx> Context<'a, 'tcx> { } } -impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { +impl<'a, 'tcx> LintContext for LateContext<'a, 'tcx> { + /// Get the overall compiler `Session` object. + fn sess(&self) -> &Session { + &self.tcx.sess + } + + fn lints(&self) -> &LintStore { + &self.lints + } + + fn mut_lints(&mut self) -> &mut LintStore { + &mut self.lints + } + + fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> { + &mut self.level_stack + } + + fn enter_attrs(&mut self, attrs: &[ast::Attribute]) { + run_lints!(self, enter_lint_attrs, late_passes, attrs); + } + + fn exit_attrs(&mut self, attrs: &[ast::Attribute]) { + run_lints!(self, exit_lint_attrs, late_passes, attrs); + } +} + +impl<'a> LintContext for EarlyContext<'a> { + /// Get the overall compiler `Session` object. + fn sess(&self) -> &Session { + &self.sess + } + + fn lints(&self) -> &LintStore { + &self.lints + } + + fn mut_lints(&mut self) -> &mut LintStore { + &mut self.lints + } + + fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> { + &mut self.level_stack + } + + fn enter_attrs(&mut self, attrs: &[ast::Attribute]) { + run_lints!(self, enter_lint_attrs, early_passes, attrs); + } + + fn exit_attrs(&mut self, attrs: &[ast::Attribute]) { + run_lints!(self, exit_lint_attrs, early_passes, attrs); + } +} + +impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { fn visit_item(&mut self, it: &hir::Item) { self.with_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_item, it); + run_lints!(cx, check_item, late_passes, it); cx.visit_ids(|v| v.visit_item(it)); - visit::walk_item(cx, it); + hir_visit::walk_item(cx, it); }) } fn visit_foreign_item(&mut self, it: &hir::ForeignItem) { self.with_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_foreign_item, it); - visit::walk_foreign_item(cx, it); + run_lints!(cx, check_foreign_item, late_passes, it); + hir_visit::walk_foreign_item(cx, it); }) } fn visit_pat(&mut self, p: &hir::Pat) { - run_lints!(self, check_pat, p); - visit::walk_pat(self, p); + run_lints!(self, check_pat, late_passes, p); + hir_visit::walk_pat(self, p); } fn visit_expr(&mut self, e: &hir::Expr) { - run_lints!(self, check_expr, e); - visit::walk_expr(self, e); + run_lints!(self, check_expr, late_passes, e); + hir_visit::walk_expr(self, e); } fn visit_stmt(&mut self, s: &hir::Stmt) { - run_lints!(self, check_stmt, s); - visit::walk_stmt(self, s); + run_lints!(self, check_stmt, late_passes, s); + hir_visit::walk_stmt(self, s); } - fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v hir::FnDecl, + fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, decl: &'v hir::FnDecl, body: &'v hir::Block, span: Span, id: ast::NodeId) { - run_lints!(self, check_fn, fk, decl, body, span, id); - visit::walk_fn(self, fk, decl, body, span); + run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); + hir_visit::walk_fn(self, fk, decl, body, span); } fn visit_struct_def(&mut self, @@ -541,116 +666,276 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { ident: ast::Ident, g: &hir::Generics, id: ast::NodeId) { - run_lints!(self, check_struct_def, s, ident, g, id); - visit::walk_struct_def(self, s); - run_lints!(self, check_struct_def_post, s, ident, g, id); + run_lints!(self, check_struct_def, late_passes, s, ident, g, id); + hir_visit::walk_struct_def(self, s); + run_lints!(self, check_struct_def_post, late_passes, s, ident, g, id); } fn visit_struct_field(&mut self, s: &hir::StructField) { self.with_lint_attrs(&s.node.attrs, |cx| { - run_lints!(cx, check_struct_field, s); - visit::walk_struct_field(cx, s); + run_lints!(cx, check_struct_field, late_passes, s); + hir_visit::walk_struct_field(cx, s); }) } fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics) { self.with_lint_attrs(&v.node.attrs, |cx| { - run_lints!(cx, check_variant, v, g); - visit::walk_variant(cx, v, g); - run_lints!(cx, check_variant_post, v, g); + run_lints!(cx, check_variant, late_passes, v, g); + hir_visit::walk_variant(cx, v, g); + run_lints!(cx, check_variant_post, late_passes, v, g); }) } fn visit_ty(&mut self, t: &hir::Ty) { - run_lints!(self, check_ty, t); - visit::walk_ty(self, t); + run_lints!(self, check_ty, late_passes, t); + hir_visit::walk_ty(self, t); } fn visit_ident(&mut self, sp: Span, id: ast::Ident) { - run_lints!(self, check_ident, sp, id); + run_lints!(self, check_ident, late_passes, sp, id); } fn visit_mod(&mut self, m: &hir::Mod, s: Span, n: ast::NodeId) { - run_lints!(self, check_mod, m, s, n); - visit::walk_mod(self, m); + run_lints!(self, check_mod, late_passes, m, s, n); + hir_visit::walk_mod(self, m); } fn visit_local(&mut self, l: &hir::Local) { - run_lints!(self, check_local, l); - visit::walk_local(self, l); + run_lints!(self, check_local, late_passes, l); + hir_visit::walk_local(self, l); } fn visit_block(&mut self, b: &hir::Block) { - run_lints!(self, check_block, b); - visit::walk_block(self, b); + run_lints!(self, check_block, late_passes, b); + hir_visit::walk_block(self, b); } fn visit_arm(&mut self, a: &hir::Arm) { - run_lints!(self, check_arm, a); - visit::walk_arm(self, a); + run_lints!(self, check_arm, late_passes, a); + hir_visit::walk_arm(self, a); } fn visit_decl(&mut self, d: &hir::Decl) { - run_lints!(self, check_decl, d); - visit::walk_decl(self, d); + run_lints!(self, check_decl, late_passes, d); + hir_visit::walk_decl(self, d); } fn visit_expr_post(&mut self, e: &hir::Expr) { - run_lints!(self, check_expr_post, e); + run_lints!(self, check_expr_post, late_passes, e); } fn visit_generics(&mut self, g: &hir::Generics) { - run_lints!(self, check_generics, g); - visit::walk_generics(self, g); + run_lints!(self, check_generics, late_passes, g); + hir_visit::walk_generics(self, g); } fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { self.with_lint_attrs(&trait_item.attrs, |cx| { - run_lints!(cx, check_trait_item, trait_item); + run_lints!(cx, check_trait_item, late_passes, trait_item); cx.visit_ids(|v| v.visit_trait_item(trait_item)); - visit::walk_trait_item(cx, trait_item); + hir_visit::walk_trait_item(cx, trait_item); }); } fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { self.with_lint_attrs(&impl_item.attrs, |cx| { - run_lints!(cx, check_impl_item, impl_item); + run_lints!(cx, check_impl_item, late_passes, impl_item); cx.visit_ids(|v| v.visit_impl_item(impl_item)); - visit::walk_impl_item(cx, impl_item); + hir_visit::walk_impl_item(cx, impl_item); }); } fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option) { - run_lints!(self, check_opt_lifetime_ref, sp, lt); + run_lints!(self, check_opt_lifetime_ref, late_passes, sp, lt); } fn visit_lifetime_ref(&mut self, lt: &hir::Lifetime) { - run_lints!(self, check_lifetime_ref, lt); + run_lints!(self, check_lifetime_ref, late_passes, lt); } fn visit_lifetime_def(&mut self, lt: &hir::LifetimeDef) { - run_lints!(self, check_lifetime_def, lt); + run_lints!(self, check_lifetime_def, late_passes, lt); } fn visit_explicit_self(&mut self, es: &hir::ExplicitSelf) { - run_lints!(self, check_explicit_self, es); - visit::walk_explicit_self(self, es); + run_lints!(self, check_explicit_self, late_passes, es); + hir_visit::walk_explicit_self(self, es); } fn visit_path(&mut self, p: &hir::Path, id: ast::NodeId) { - run_lints!(self, check_path, p, id); - visit::walk_path(self, p); + run_lints!(self, check_path, late_passes, p, id); + hir_visit::walk_path(self, p); + } + + fn visit_attribute(&mut self, attr: &ast::Attribute) { + run_lints!(self, check_attribute, late_passes, attr); + } +} + +impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { + fn visit_item(&mut self, it: &ast::Item) { + self.with_lint_attrs(&it.attrs, |cx| { + run_lints!(cx, check_item, early_passes, it); + cx.visit_ids(|v| v.visit_item(it)); + ast_visit::walk_item(cx, it); + }) + } + + fn visit_foreign_item(&mut self, it: &ast::ForeignItem) { + self.with_lint_attrs(&it.attrs, |cx| { + run_lints!(cx, check_foreign_item, early_passes, it); + ast_visit::walk_foreign_item(cx, it); + }) + } + + fn visit_pat(&mut self, p: &ast::Pat) { + run_lints!(self, check_pat, early_passes, p); + ast_visit::walk_pat(self, p); + } + + fn visit_expr(&mut self, e: &ast::Expr) { + run_lints!(self, check_expr, early_passes, e); + ast_visit::walk_expr(self, e); + } + + fn visit_stmt(&mut self, s: &ast::Stmt) { + run_lints!(self, check_stmt, early_passes, s); + ast_visit::walk_stmt(self, s); + } + + fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, decl: &'v ast::FnDecl, + body: &'v ast::Block, span: Span, id: ast::NodeId) { + run_lints!(self, check_fn, early_passes, fk, decl, body, span, id); + ast_visit::walk_fn(self, fk, decl, body, span); + } + + fn visit_struct_def(&mut self, + s: &ast::StructDef, + ident: ast::Ident, + g: &ast::Generics, + id: ast::NodeId) { + run_lints!(self, check_struct_def, early_passes, s, ident, g, id); + ast_visit::walk_struct_def(self, s); + run_lints!(self, check_struct_def_post, early_passes, s, ident, g, id); + } + + fn visit_struct_field(&mut self, s: &ast::StructField) { + self.with_lint_attrs(&s.node.attrs, |cx| { + run_lints!(cx, check_struct_field, early_passes, s); + ast_visit::walk_struct_field(cx, s); + }) + } + + fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) { + self.with_lint_attrs(&v.node.attrs, |cx| { + run_lints!(cx, check_variant, early_passes, v, g); + ast_visit::walk_variant(cx, v, g); + run_lints!(cx, check_variant_post, early_passes, v, g); + }) + } + + fn visit_ty(&mut self, t: &ast::Ty) { + run_lints!(self, check_ty, early_passes, t); + ast_visit::walk_ty(self, t); + } + + fn visit_ident(&mut self, sp: Span, id: ast::Ident) { + run_lints!(self, check_ident, early_passes, sp, id); + } + + fn visit_mod(&mut self, m: &ast::Mod, s: Span, n: ast::NodeId) { + run_lints!(self, check_mod, early_passes, m, s, n); + ast_visit::walk_mod(self, m); + } + + fn visit_local(&mut self, l: &ast::Local) { + run_lints!(self, check_local, early_passes, l); + ast_visit::walk_local(self, l); + } + + fn visit_block(&mut self, b: &ast::Block) { + run_lints!(self, check_block, early_passes, b); + ast_visit::walk_block(self, b); + } + + fn visit_arm(&mut self, a: &ast::Arm) { + run_lints!(self, check_arm, early_passes, a); + ast_visit::walk_arm(self, a); + } + + fn visit_decl(&mut self, d: &ast::Decl) { + run_lints!(self, check_decl, early_passes, d); + ast_visit::walk_decl(self, d); + } + + fn visit_expr_post(&mut self, e: &ast::Expr) { + run_lints!(self, check_expr_post, early_passes, e); + } + + fn visit_generics(&mut self, g: &ast::Generics) { + run_lints!(self, check_generics, early_passes, g); + ast_visit::walk_generics(self, g); + } + + fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { + self.with_lint_attrs(&trait_item.attrs, |cx| { + run_lints!(cx, check_trait_item, early_passes, trait_item); + cx.visit_ids(|v| v.visit_trait_item(trait_item)); + ast_visit::walk_trait_item(cx, trait_item); + }); + } + + fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { + self.with_lint_attrs(&impl_item.attrs, |cx| { + run_lints!(cx, check_impl_item, early_passes, impl_item); + cx.visit_ids(|v| v.visit_impl_item(impl_item)); + ast_visit::walk_impl_item(cx, impl_item); + }); + } + + fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option) { + run_lints!(self, check_opt_lifetime_ref, early_passes, sp, lt); + } + + fn visit_lifetime_ref(&mut self, lt: &ast::Lifetime) { + run_lints!(self, check_lifetime_ref, early_passes, lt); + } + + fn visit_lifetime_def(&mut self, lt: &ast::LifetimeDef) { + run_lints!(self, check_lifetime_def, early_passes, lt); + } + + fn visit_explicit_self(&mut self, es: &ast::ExplicitSelf) { + run_lints!(self, check_explicit_self, early_passes, es); + ast_visit::walk_explicit_self(self, es); + } + + fn visit_path(&mut self, p: &ast::Path, id: ast::NodeId) { + run_lints!(self, check_path, early_passes, p, id); + ast_visit::walk_path(self, p); } fn visit_attribute(&mut self, attr: &ast::Attribute) { - run_lints!(self, check_attribute, attr); + run_lints!(self, check_attribute, early_passes, attr); } } // Output any lints that were previously added to the session. -impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> { +impl<'a, 'tcx> IdVisitingOperation for LateContext<'a, 'tcx> { fn visit_id(&mut self, id: ast::NodeId) { - match self.tcx.sess.lints.borrow_mut().remove(&id) { + match self.sess().lints.borrow_mut().remove(&id) { + None => {} + Some(lints) => { + for (lint_id, span, msg) in lints { + self.span_lint(lint_id.lint, span, &msg[..]) + } + } + } + } +} +impl<'a> IdVisitingOperation for EarlyContext<'a> { + fn visit_id(&mut self, id: ast::NodeId) { + match self.sess.lints.borrow_mut().remove(&id) { None => {} Some(lints) => { for (lint_id, span, msg) in lints { @@ -661,7 +946,7 @@ impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> { } } -// This lint pass is defined here because it touches parts of the `Context` +// This lint pass is defined here because it touches parts of the `LateContext` // that we don't want to expose. It records the lint level at certain AST // nodes, so that the variant size difference check in trans can call // `raw_emit_lint`. @@ -672,8 +957,10 @@ impl LintPass for GatherNodeLevels { fn get_lints(&self) -> LintArray { lint_array!() } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl LateLintPass for GatherNodeLevels { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemEnum(..) => { let lint_id = LintId::of(builtin::VARIANT_SIZE_DIFFERENCES); @@ -698,21 +985,21 @@ pub fn check_crate(tcx: &ty::ctxt, krate: &hir::Crate, exported_items: &ExportedItems) { - let mut cx = Context::new(tcx, krate, exported_items); + let mut cx = LateContext::new(tcx, krate, exported_items); // Visit the whole crate. cx.with_lint_attrs(&krate.attrs, |cx| { cx.visit_id(ast::CRATE_NODE_ID); cx.visit_ids(|v| { v.visited_outermost = true; - visit::walk_crate(v, krate); + hir_visit::walk_crate(v, krate); }); // since the root module isn't visited as an item (because it isn't an // item), warn for it here. - run_lints!(cx, check_crate, krate); + run_lints!(cx, check_crate, late_passes, krate); - visit::walk_crate(cx, krate); + hir_visit::walk_crate(cx, krate); }); // If we missed any lints added to the session, then there's a bug somewhere @@ -727,3 +1014,35 @@ pub fn check_crate(tcx: &ty::ctxt, *tcx.node_lint_levels.borrow_mut() = cx.node_levels.into_inner(); } + +pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { + let mut cx = EarlyContext::new(sess, krate); + + // Visit the whole crate. + cx.with_lint_attrs(&krate.attrs, |cx| { + cx.visit_id(ast::CRATE_NODE_ID); + cx.visit_ids(|v| { + v.visited_outermost = true; + ast_visit::walk_crate(v, krate); + }); + + // since the root module isn't visited as an item (because it isn't an + // item), warn for it here. + run_lints!(cx, check_crate, early_passes, krate); + + ast_visit::walk_crate(cx, krate); + }); + + // Put the lint store back in the session. + mem::replace(&mut *sess.lint_store.borrow_mut(), cx.lints); + + // If we missed any lints added to the session, then there's a bug somewhere + // in the iteration code. + for (_, v) in sess.lints.borrow().iter() { + for &(lint, span, ref msg) in v { + sess.span_bug(span, + &format!("unprocessed lint {}: {}", + lint.as_str(), *msg)) + } + } +} diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 11a1852ed2509..e52b6e91f68cd 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -35,10 +35,12 @@ use std::hash; use std::ascii::AsciiExt; use syntax::codemap::Span; use rustc_front::visit::FnKind; +use syntax::visit as ast_visit; use syntax::ast; use rustc_front::hir; -pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs, +pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, + raw_emit_lint, check_crate, check_ast_crate, gather_attrs, GatherNodeLevels}; /// Specification of a single lint. @@ -109,14 +111,6 @@ macro_rules! lint_array { ($( $lint:expr ),*) => ( pub type LintArray = &'static [&'static &'static Lint]; -/// Trait for types providing lint checks. -/// -/// Each `check` method checks a single syntax node, and should not -/// invoke methods recursively (unlike `Visitor`). By default they -/// do nothing. -// -// FIXME: eliminate the duplication with `Visitor`. But this also -// contains a few lint-specific methods with no equivalent in `Visitor`. pub trait LintPass { /// Get descriptions of the lints this `LintPass` object can emit. /// @@ -125,51 +119,111 @@ pub trait LintPass { /// parts of the compiler. If you want enforced access restrictions for your /// `Lint`, make it a private `static` item in its own module. fn get_lints(&self) -> LintArray; +} + - fn check_crate(&mut self, _: &Context, _: &hir::Crate) { } - fn check_ident(&mut self, _: &Context, _: Span, _: ast::Ident) { } - fn check_mod(&mut self, _: &Context, _: &hir::Mod, _: Span, _: ast::NodeId) { } - fn check_foreign_item(&mut self, _: &Context, _: &hir::ForeignItem) { } - fn check_item(&mut self, _: &Context, _: &hir::Item) { } - fn check_local(&mut self, _: &Context, _: &hir::Local) { } - fn check_block(&mut self, _: &Context, _: &hir::Block) { } - fn check_stmt(&mut self, _: &Context, _: &hir::Stmt) { } - fn check_arm(&mut self, _: &Context, _: &hir::Arm) { } - fn check_pat(&mut self, _: &Context, _: &hir::Pat) { } - fn check_decl(&mut self, _: &Context, _: &hir::Decl) { } - fn check_expr(&mut self, _: &Context, _: &hir::Expr) { } - fn check_expr_post(&mut self, _: &Context, _: &hir::Expr) { } - fn check_ty(&mut self, _: &Context, _: &hir::Ty) { } - fn check_generics(&mut self, _: &Context, _: &hir::Generics) { } - fn check_fn(&mut self, _: &Context, +/// Trait for types providing lint checks. +/// +/// Each `check` method checks a single syntax node, and should not +/// invoke methods recursively (unlike `Visitor`). By default they +/// do nothing. +// +// FIXME: eliminate the duplication with `Visitor`. But this also +// contains a few lint-specific methods with no equivalent in `Visitor`. +pub trait LateLintPass: LintPass { + fn check_ident(&mut self, _: &LateContext, _: Span, _: ast::Ident) { } + fn check_crate(&mut self, _: &LateContext, _: &hir::Crate) { } + fn check_mod(&mut self, _: &LateContext, _: &hir::Mod, _: Span, _: ast::NodeId) { } + fn check_foreign_item(&mut self, _: &LateContext, _: &hir::ForeignItem) { } + fn check_item(&mut self, _: &LateContext, _: &hir::Item) { } + fn check_local(&mut self, _: &LateContext, _: &hir::Local) { } + fn check_block(&mut self, _: &LateContext, _: &hir::Block) { } + fn check_stmt(&mut self, _: &LateContext, _: &hir::Stmt) { } + fn check_arm(&mut self, _: &LateContext, _: &hir::Arm) { } + fn check_pat(&mut self, _: &LateContext, _: &hir::Pat) { } + fn check_decl(&mut self, _: &LateContext, _: &hir::Decl) { } + fn check_expr(&mut self, _: &LateContext, _: &hir::Expr) { } + fn check_expr_post(&mut self, _: &LateContext, _: &hir::Expr) { } + fn check_ty(&mut self, _: &LateContext, _: &hir::Ty) { } + fn check_generics(&mut self, _: &LateContext, _: &hir::Generics) { } + fn check_fn(&mut self, _: &LateContext, _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { } - fn check_trait_item(&mut self, _: &Context, _: &hir::TraitItem) { } - fn check_impl_item(&mut self, _: &Context, _: &hir::ImplItem) { } - fn check_struct_def(&mut self, _: &Context, + fn check_trait_item(&mut self, _: &LateContext, _: &hir::TraitItem) { } + fn check_impl_item(&mut self, _: &LateContext, _: &hir::ImplItem) { } + fn check_struct_def(&mut self, _: &LateContext, _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, _: ast::NodeId) { } - fn check_struct_def_post(&mut self, _: &Context, + fn check_struct_def_post(&mut self, _: &LateContext, _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, _: ast::NodeId) { } - fn check_struct_field(&mut self, _: &Context, _: &hir::StructField) { } - fn check_variant(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) { } - fn check_variant_post(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) { } - fn check_opt_lifetime_ref(&mut self, _: &Context, _: Span, _: &Option) { } - fn check_lifetime_ref(&mut self, _: &Context, _: &hir::Lifetime) { } - fn check_lifetime_def(&mut self, _: &Context, _: &hir::LifetimeDef) { } - fn check_explicit_self(&mut self, _: &Context, _: &hir::ExplicitSelf) { } - fn check_mac(&mut self, _: &Context, _: &ast::Mac) { } - fn check_path(&mut self, _: &Context, _: &hir::Path, _: ast::NodeId) { } - fn check_attribute(&mut self, _: &Context, _: &ast::Attribute) { } + fn check_struct_field(&mut self, _: &LateContext, _: &hir::StructField) { } + fn check_variant(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { } + fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { } + fn check_opt_lifetime_ref(&mut self, _: &LateContext, _: Span, _: &Option) { } + fn check_lifetime_ref(&mut self, _: &LateContext, _: &hir::Lifetime) { } + fn check_lifetime_def(&mut self, _: &LateContext, _: &hir::LifetimeDef) { } + fn check_explicit_self(&mut self, _: &LateContext, _: &hir::ExplicitSelf) { } + // Note that you shouldn't implement both check_mac and check_ast_mac, + // because then your lint will be called twice. Prefer check_ast_mac. + fn check_mac(&mut self, _: &LateContext, _: &ast::Mac) { } + fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { } + fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { } + + /// Called when entering a syntax node that can have lint attributes such + /// as `#[allow(...)]`. Called with *all* the attributes of that node. + fn enter_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { } + + /// Counterpart to `enter_lint_attrs`. + fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { } +} + +pub trait EarlyLintPass: LintPass { + fn check_ident(&mut self, _: &EarlyContext, _: Span, _: ast::Ident) { } + fn check_crate(&mut self, _: &EarlyContext, _: &ast::Crate) { } + fn check_mod(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { } + fn check_foreign_item(&mut self, _: &EarlyContext, _: &ast::ForeignItem) { } + fn check_item(&mut self, _: &EarlyContext, _: &ast::Item) { } + fn check_local(&mut self, _: &EarlyContext, _: &ast::Local) { } + fn check_block(&mut self, _: &EarlyContext, _: &ast::Block) { } + fn check_stmt(&mut self, _: &EarlyContext, _: &ast::Stmt) { } + fn check_arm(&mut self, _: &EarlyContext, _: &ast::Arm) { } + fn check_pat(&mut self, _: &EarlyContext, _: &ast::Pat) { } + fn check_decl(&mut self, _: &EarlyContext, _: &ast::Decl) { } + fn check_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { } + fn check_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { } + fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { } + fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { } + fn check_fn(&mut self, _: &EarlyContext, + _: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { } + fn check_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { } + fn check_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { } + fn check_struct_def(&mut self, _: &EarlyContext, + _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } + fn check_struct_def_post(&mut self, _: &EarlyContext, + _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } + fn check_struct_field(&mut self, _: &EarlyContext, _: &ast::StructField) { } + fn check_variant(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } + fn check_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } + fn check_opt_lifetime_ref(&mut self, + _: &EarlyContext, + _: Span, + _: &Option) { } + fn check_lifetime_ref(&mut self, _: &EarlyContext, _: &ast::Lifetime) { } + fn check_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { } + fn check_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { } + fn check_mac(&mut self, _: &EarlyContext, _: &ast::Mac) { } + fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { } + fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { } /// Called when entering a syntax node that can have lint attributes such /// as `#[allow(...)]`. Called with *all* the attributes of that node. - fn enter_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { } + fn enter_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } /// Counterpart to `enter_lint_attrs`. - fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { } + fn exit_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } } /// A lint pass boxed up as a trait object. -pub type LintPassObject = Box; +pub type EarlyLintPassObject = Box; +pub type LateLintPassObject = Box; /// Identifies a lint known to the compiler. #[derive(Clone, Copy)] diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 3f6385ad82cc4..60aebd9cd4226 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -354,7 +354,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprAddrOf(_, ref e) | hir::ExprCast(ref e, _) | hir::ExprUnary(_, ref e) | - hir::ExprParen(ref e) | hir::ExprField(ref e, _) | hir::ExprTupField(ref e, _) => { self.straightline(expr, pred, Some(&**e).into_iter()) diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index d0451026d27ac..7da2c8f1492df 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -678,7 +678,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, let mut callee = &**callee; loop { callee = match callee.node { - hir::ExprParen(ref inner) => &**inner, hir::ExprBlock(ref block) => match block.expr { Some(ref tail) => &**tail, None => break @@ -763,7 +762,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, hir::ExprField(..) | hir::ExprTupField(..) | hir::ExprVec(_) | - hir::ExprParen(..) | hir::ExprTup(..) => {} // Conditional control flow (possible to implement). diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 11be35a24f5f7..8f5cf36278d52 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -996,7 +996,6 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, hir::ExprLit(ref lit) => { lit_to_const(&**lit, ety) } - hir::ExprParen(ref e) => try!(eval_const_expr_partial(tcx, &**e, ty_hint)), hir::ExprBlock(ref block) => { match block.expr { Some(ref expr) => try!(eval_const_expr_partial(tcx, &**expr, ty_hint)), diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a8fed5eab16be..c067c9b4d6313 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -362,9 +362,6 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { let cmt = return_if_err!(self.mc.cat_expr(expr)); self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause); - // Note: Unlike consume, we can ignore ExprParen. cat_expr - // already skips over them, and walk will uncover any - // attachments or whatever. self.walk_expr(expr) } @@ -378,10 +375,6 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { self.walk_adjustment(expr); match expr.node { - hir::ExprParen(ref subexpr) => { - self.walk_expr(&**subexpr) - } - hir::ExprPath(..) => { } hir::ExprUnary(hir::UnDeref, ref base) => { // *base diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 561760b29f19e..9bb19bb37d8e4 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -495,7 +495,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { hir::ExprAgain(_) | hir::ExprLit(_) | hir::ExprRet(..) | hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) | hir::ExprStruct(..) | hir::ExprRepeat(..) | - hir::ExprParen(..) | hir::ExprInlineAsm(..) | hir::ExprBox(..) | + hir::ExprInlineAsm(..) | hir::ExprBox(..) | hir::ExprRange(..) => { visit::walk_expr(ir, expr); } @@ -1161,8 +1161,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprBox(None, ref e) | hir::ExprAddrOf(_, ref e) | hir::ExprCast(ref e, _) | - hir::ExprUnary(_, ref e) | - hir::ExprParen(ref e) => { + hir::ExprUnary(_, ref e) => { self.propagate_through_expr(&**e, succ) } @@ -1435,7 +1434,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprRet(..) | hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) | hir::ExprBlock(..) | hir::ExprAddrOf(..) | - hir::ExprStruct(..) | hir::ExprRepeat(..) | hir::ExprParen(..) | + hir::ExprStruct(..) | hir::ExprRepeat(..) | hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) | hir::ExprRange(..) => { visit::walk_expr(this, expr); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index dd2f48d25b4b0..2078ee2c57b8f 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -519,10 +519,6 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { self.cat_def(expr.id, expr.span, expr_ty, def) } - hir::ExprParen(ref e) => { - self.cat_expr(&**e) - } - hir::ExprAddrOf(..) | hir::ExprCall(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) | hir::ExprClosure(..) | hir::ExprRet(..) | diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index f08cbb4143851..c26982ff5ede1 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -997,8 +997,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { hir::ExprUnary(hir::UnUniq, ref subexpr) => { record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id); } - hir::ExprCast(ref subexpr, _) | - hir::ExprParen(ref subexpr) => { + hir::ExprCast(ref subexpr, _) => { record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id) } hir::ExprBlock(ref block) => { @@ -1047,8 +1046,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { hir::ExprUnary(hir::UnDeref, ref subexpr) | hir::ExprField(ref subexpr, _) | hir::ExprTupField(ref subexpr, _) | - hir::ExprIndex(ref subexpr, _) | - hir::ExprParen(ref subexpr) => { + hir::ExprIndex(ref subexpr, _) => { expr = &**subexpr; } _ => { diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index fdf23c455ba2f..972f7242808b6 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -2089,8 +2089,6 @@ impl<'tcx> ctxt<'tcx> { hir::ExprCast(..) => { false } - - hir::ExprParen(ref e) => self.expr_is_lval(e), } } diff --git a/src/librustc/middle/ty/sty.rs b/src/librustc/middle/ty/sty.rs index 2d578fd0ea543..44f97a6b9e3c3 100644 --- a/src/librustc/middle/ty/sty.rs +++ b/src/librustc/middle/ty/sty.rs @@ -899,6 +899,14 @@ impl<'tcx> TyS<'tcx> { } } + pub fn is_phantom_data(&self) -> bool { + if let TyStruct(def, _) = self.sty { + def.is_phantom_data() + } else { + false + } + } + pub fn is_bool(&self) -> bool { self.sty == TyBool } pub fn is_param(&self, space: subst::ParamSpace, index: u32) -> bool { diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index e79721b4347a6..50ca092dfe64e 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -10,7 +10,7 @@ //! Used by plugin crates to tell `rustc` about the plugins they provide. -use lint::{LintPassObject, LintId, Lint}; +use lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint}; use session::Session; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT}; @@ -48,7 +48,10 @@ pub struct Registry<'a> { pub syntax_exts: Vec, #[doc(hidden)] - pub lint_passes: Vec, + pub early_lint_passes: Vec, + + #[doc(hidden)] + pub late_lint_passes: Vec, #[doc(hidden)] pub lint_groups: HashMap<&'static str, Vec>, @@ -68,7 +71,8 @@ impl<'a> Registry<'a> { args_hidden: None, krate_span: krate.span, syntax_exts: vec!(), - lint_passes: vec!(), + early_lint_passes: vec!(), + late_lint_passes: vec!(), lint_groups: HashMap::new(), llvm_passes: vec!(), attributes: vec!(), @@ -89,7 +93,6 @@ impl<'a> Registry<'a> { /// Register a syntax extension of any kind. /// /// This is the most general hook into `libsyntax`'s expansion behavior. - #[allow(deprecated)] pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) { self.syntax_exts.push((name, match extension { NormalTT(ext, _, allow_internal_unstable) => { @@ -118,10 +121,14 @@ impl<'a> Registry<'a> { } /// Register a compiler lint pass. - pub fn register_lint_pass(&mut self, lint_pass: LintPassObject) { - self.lint_passes.push(lint_pass); + pub fn register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject) { + self.early_lint_passes.push(lint_pass); } + /// Register a compiler lint pass. + pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) { + self.late_lint_passes.push(lint_pass); + } /// Register a lint group. pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) { self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect()); diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ad0eb4d53fe26..30f43baabba2f 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -601,6 +601,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "For every macro invocation, print its name and arguments"), enable_nonzeroing_move_hints: bool = (false, parse_bool, "Force nonzeroing move optimization on"), + keep_mtwt_tables: bool = (false, parse_bool, + "Don't clear the resolution tables after analysis"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 36fc814234d7f..7134066d08ce7 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -249,7 +249,6 @@ mod svh_visitor { SawExprInlineAsm(&'a hir::InlineAsm), SawExprStruct, SawExprRepeat, - SawExprParen, } fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> { @@ -283,7 +282,6 @@ mod svh_visitor { ExprInlineAsm(ref asm) => SawExprInlineAsm(asm), ExprStruct(..) => SawExprStruct, ExprRepeat(..) => SawExprRepeat, - ExprParen(..) => SawExprParen, } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f3038624ac107..ce04a5befd939 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -129,10 +129,12 @@ pub fn compile_input(sess: Session, &ast_map.krate(), &id[..])); + time(sess.time_passes(), "early lint checks", || { + lint::check_ast_crate(&sess, &expanded_crate) + }); phase_3_run_analysis_passes(sess, ast_map, - &expanded_crate, &arenas, id, control.make_glob_map, @@ -480,13 +482,16 @@ pub fn phase_2_configure_and_expand(sess: &Session, } }); - let Registry { syntax_exts, lint_passes, lint_groups, + let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, .. } = registry; { let mut ls = sess.lint_store.borrow_mut(); - for pass in lint_passes { - ls.register_pass(Some(sess), true, pass); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); } for (name, to) in lint_groups { @@ -641,7 +646,6 @@ pub fn make_map<'ast>(sess: &Session, /// structures carrying the results of the analysis. pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session, ast_map: front::map::Map<'tcx>, - ast_crate: &ast::Crate, arenas: &'tcx ty::CtxtArenas<'tcx>, name: String, make_glob_map: resolve::MakeGlobMap, @@ -671,7 +675,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session, || resolve::resolve_crate(&sess, &ast_map, make_glob_map)); // Discard MTWT tables that aren't required past resolution. - syntax::ext::mtwt::clear_tables(); + if !sess.opts.debugging_opts.keep_mtwt_tables { + syntax::ext::mtwt::clear_tables(); + } let named_region_map = time(time_passes, "lifetime resolution", || middle::resolve_lifetime::krate(&sess, krate, &def_map)); @@ -765,7 +771,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session, &tcx.sess, lib_features_used)); time(time_passes, "lint checking", || - lint::check_crate(tcx, &lower_crate(ast_crate), &exported_items)); + lint::check_crate(tcx, krate, &exported_items)); // The above three passes generate errors w/o aborting tcx.sess.abort_if_errors(); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index dc36a4ab93c6a..75b57341d48df 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -157,7 +157,6 @@ impl PpSourceMode { fn call_with_pp_support_hir<'tcx, A, B, F>(&self, sess: Session, ast_map: &hir_map::Map<'tcx>, - ast_crate: &ast::Crate, arenas: &'tcx ty::CtxtArenas<'tcx>, id: String, payload: B, @@ -180,7 +179,6 @@ impl PpSourceMode { PpmTyped => { driver::phase_3_run_analysis_passes(sess, ast_map.clone(), - ast_crate, arenas, id, resolve::MakeGlobMap::No, @@ -715,7 +713,7 @@ pub fn pretty_print_input(sess: Session, (PpmHir(s), None) => { let out: &mut Write = &mut out; s.call_with_pp_support_hir( - sess, &ast_map.unwrap(), &krate, &arenas, id, box out, |annotation, out, krate| { + sess, &ast_map.unwrap(), &arenas, id, box out, |annotation, out, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust_hir::print_crate(sess.codemap(), @@ -733,7 +731,6 @@ pub fn pretty_print_input(sess: Session, let out: &mut Write = &mut out; s.call_with_pp_support_hir(sess, &ast_map.unwrap(), - &krate, &arenas, id, (out,uii), @@ -782,7 +779,6 @@ pub fn pretty_print_input(sess: Session, let variants = gather_flowgraph_variants(&sess); driver::phase_3_run_analysis_passes(sess, ast_map, - &krate, &arenas, id, resolve::MakeGlobMap::No, diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index 0ff972f830f01..1371799a051e2 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -415,7 +415,7 @@ pub fn noop_fold_foreign_mod(ForeignMod {abi, items}: ForeignMod, } pub fn noop_fold_variant(v: P, fld: &mut T) -> P { - v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr, vis}, span}| Spanned { + v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr}, span}| Spanned { node: Variant_ { id: fld.new_id(id), name: name, @@ -430,7 +430,6 @@ pub fn noop_fold_variant(v: P, fld: &mut T) -> P { } }, disr_expr: disr_expr.map(|e| fld.fold_expr(e)), - vis: vis, }, span: fld.new_span(span), }) @@ -1164,7 +1163,6 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> fields.move_map(|x| folder.fold_field(x)), maybe_expr.map(|x| folder.fold_expr(x))) }, - ExprParen(ex) => ExprParen(folder.fold_expr(ex)) }, span: folder.new_span(span) } diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index f329aa49daabc..c6426807db45b 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -703,9 +703,6 @@ pub enum Expr_ { /// For example, `[1u8; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. ExprRepeat(P, P), - - /// No-op: used solely so we can pretty-print faithfully - ExprParen(P) } /// The explicit Self type in a "qualified path". The actual @@ -1055,7 +1052,6 @@ pub struct Variant_ { pub id: NodeId, /// Explicit discriminant, eg `Foo = 1` pub disr_expr: Option>, - pub vis: Visibility, } pub type Variant = Spanned; diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index 38f9ec2c8e6bc..f7f938eb92482 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -147,7 +147,6 @@ pub fn lower_variant(v: &Variant) -> P { } }, disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(e)), - vis: lower_visibility(v.node.vis), }, span: v.span, }) @@ -810,7 +809,9 @@ pub fn lower_expr(e: &Expr) -> P { fields.iter().map(|x| lower_field(x)).collect(), maybe_expr.as_ref().map(|x| lower_expr(x))) }, - ExprParen(ref ex) => hir::ExprParen(lower_expr(ex)), + ExprParen(ref ex) => { + return lower_expr(ex); + } ExprIfLet(..) | ExprWhileLet(..) | ExprForLoop(..) | diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index d8d85135dd8f5..3930eec756130 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -944,7 +944,6 @@ impl<'a> State<'a> { } pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> { - try!(self.print_visibility(v.node.vis)); match v.node.kind { hir::TupleVariantKind(ref args) => { try!(self.print_ident(v.node.name)); @@ -1218,34 +1217,34 @@ impl<'a> State<'a> { fields: &[hir::Field], wth: &Option>) -> io::Result<()> { try!(self.print_path(path, true, 0)); - if !(fields.is_empty() && wth.is_none()) { - try!(word(&mut self.s, "{")); - try!(self.commasep_cmnt( - Consistent, - &fields[..], - |s, field| { - try!(s.ibox(indent_unit)); - try!(s.print_ident(field.ident.node)); - try!(s.word_space(":")); - try!(s.print_expr(&*field.expr)); - s.end() - }, - |f| f.span)); - match *wth { - Some(ref expr) => { - try!(self.ibox(indent_unit)); - if !fields.is_empty() { - try!(word(&mut self.s, ",")); - try!(space(&mut self.s)); - } - try!(word(&mut self.s, "..")); - try!(self.print_expr(&**expr)); - try!(self.end()); + try!(word(&mut self.s, "{")); + try!(self.commasep_cmnt( + Consistent, + &fields[..], + |s, field| { + try!(s.ibox(indent_unit)); + try!(s.print_ident(field.ident.node)); + try!(s.word_space(":")); + try!(s.print_expr(&*field.expr)); + s.end() + }, + |f| f.span)); + match *wth { + Some(ref expr) => { + try!(self.ibox(indent_unit)); + if !fields.is_empty() { + try!(word(&mut self.s, ",")); + try!(space(&mut self.s)); } - _ => try!(word(&mut self.s, ",")), + try!(word(&mut self.s, "..")); + try!(self.print_expr(&**expr)); + try!(self.end()); + } + _ => if !fields.is_empty() { + try!(word(&mut self.s, ",")) } - try!(word(&mut self.s, "}")); } + try!(word(&mut self.s, "}")); Ok(()) } @@ -1556,11 +1555,6 @@ impl<'a> State<'a> { try!(self.pclose()); } - hir::ExprParen(ref e) => { - try!(self.popen()); - try!(self.print_expr(&**e)); - try!(self.pclose()); - } } try!(self.ann.post(self, NodeExpr(expr))); self.end() diff --git a/src/librustc_front/visit.rs b/src/librustc_front/visit.rs index 4a3e74fd3fef7..d9b4f37411420 100644 --- a/src/librustc_front/visit.rs +++ b/src/librustc_front/visit.rs @@ -814,9 +814,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprRet(ref optional_expression) => { walk_expr_opt(visitor, optional_expression) } - ExprParen(ref subexpression) => { - visitor.visit_expr(&**subexpression) - } ExprInlineAsm(ref ia) => { for input in &ia.inputs { let (_, ref input) = *input; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 816b84f3d46b1..5b875e6acbc04 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -38,7 +38,8 @@ use middle::const_eval::{eval_const_expr_partial, ConstVal}; use middle::const_eval::EvalHint::ExprTypeChecked; use rustc::front::map as hir_map; use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet}; -use lint::{Level, Context, LintPass, LintArray, Lint}; +use lint::{Level, LateContext, EarlyContext, LintContext, LintArray, Lint}; +use lint::{LintPass, EarlyLintPass, LateLintPass}; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -48,7 +49,7 @@ use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; use syntax::{abi, ast}; use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::{self, Span}; -use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType}; +use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType, emit_feature_err, GateIssue}; use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; use syntax::ptr::P; @@ -72,8 +73,10 @@ impl LintPass for WhileTrue { fn get_lints(&self) -> LintArray { lint_array!(WHILE_TRUE) } +} - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { +impl LateLintPass for WhileTrue { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprWhile(ref cond, _, _) = e.node { if let hir::ExprLit(ref lit) = cond.node { if let ast::LitBool(true) = lit.node { @@ -121,8 +124,10 @@ impl LintPass for TypeLimits { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS) } +} - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { +impl LateLintPass for TypeLimits { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnNeg, ref expr) => { match expr.node { @@ -154,9 +159,6 @@ impl LintPass for TypeLimits { self.negated_expr_id = expr.id; } }, - hir::ExprParen(ref expr) if self.negated_expr_id == e.id => { - self.negated_expr_id = expr.id; - }, hir::ExprBinary(binop, ref l, ref r) => { if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) { cx.span_lint(UNUSED_COMPARISONS, e.span, @@ -377,15 +379,14 @@ impl LintPass for TypeLimits { } } - fn check_unsigned_negation_feature(cx: &Context, span: Span) { + fn check_unsigned_negation_feature(cx: &LateContext, span: Span) { if !cx.sess().features.borrow().negate_unsigned { - // FIXME(#27141): change this to syntax::feature_gate::emit_feature_err… - cx.sess().span_warn(span, - "unary negation of unsigned integers will be feature gated in the future"); - // …and remove following two expressions. - if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; } - cx.sess().fileline_help(span, "add #![feature(negate_unsigned)] to the \ - crate attributes to enable the gate in advance"); + emit_feature_err( + &cx.sess().parse_sess.span_diagnostic, + "negate_unsigned", + span, + GateIssue::Language, + "unary negation of unsigned integers may be removed in the future"); } } } @@ -398,7 +399,7 @@ declare_lint! { } struct ImproperCTypesVisitor<'a, 'tcx: 'a> { - cx: &'a Context<'a, 'tcx> + cx: &'a LateContext<'a, 'tcx> } enum FfiResult { @@ -702,14 +703,16 @@ impl LintPass for ImproperCTypes { fn get_lints(&self) -> LintArray { lint_array!(IMPROPER_CTYPES) } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { - fn check_ty(cx: &Context, ty: &hir::Ty) { +impl LateLintPass for ImproperCTypes { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + fn check_ty(cx: &LateContext, ty: &hir::Ty) { let mut vis = ImproperCTypesVisitor { cx: cx }; vis.visit_ty(ty); } - fn check_foreign_fn(cx: &Context, decl: &hir::FnDecl) { + fn check_foreign_fn(cx: &LateContext, decl: &hir::FnDecl) { for input in &decl.inputs { check_ty(cx, &*input.ty); } @@ -747,7 +750,7 @@ declare_lint! { pub struct BoxPointers; impl BoxPointers { - fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>, + fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) { for leaf_ty in ty.walk() { if let ty::TyBox(_) = leaf_ty.sty { @@ -762,8 +765,10 @@ impl LintPass for BoxPointers { fn get_lints(&self) -> LintArray { lint_array!(BOX_POINTERS) } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl LateLintPass for BoxPointers { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) | hir::ItemTy(..) | @@ -786,7 +791,7 @@ impl LintPass for BoxPointers { } } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { let ty = cx.tcx.node_id_to_type(e.id); self.check_heap_type(cx, e.span, ty); } @@ -799,7 +804,7 @@ declare_lint! { } struct RawPtrDeriveVisitor<'a, 'tcx: 'a> { - cx: &'a Context<'a, 'tcx> + cx: &'a LateContext<'a, 'tcx> } impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> { @@ -831,8 +836,10 @@ impl LintPass for RawPointerDerive { fn get_lints(&self) -> LintArray { lint_array!(RAW_POINTER_DERIVE) } +} - fn check_item(&mut self, cx: &Context, item: &hir::Item) { +impl LateLintPass for RawPointerDerive { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !attr::contains_name(&item.attrs, "automatically_derived") { return; } @@ -887,8 +894,10 @@ impl LintPass for UnusedAttributes { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_ATTRIBUTES) } +} - fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) { +impl LateLintPass for UnusedAttributes { + fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) { // Note that check_name() marks the attribute as used if it matches. for &(ref name, ty, _) in KNOWN_ATTRIBUTES { match ty { @@ -947,8 +956,10 @@ impl LintPass for PathStatements { fn get_lints(&self) -> LintArray { lint_array!(PATH_STATEMENTS) } +} - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { +impl LateLintPass for PathStatements { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { match s.node { hir::StmtSemi(ref expr, _) => { match expr.node { @@ -981,8 +992,10 @@ impl LintPass for UnusedResults { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS) } +} - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { +impl LateLintPass for UnusedResults { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { hir::StmtSemi(ref expr, _) => &**expr, _ => return @@ -1015,7 +1028,7 @@ impl LintPass for UnusedResults { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } - fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool { + fn check_must_use(cx: &LateContext, attrs: &[ast::Attribute], sp: Span) -> bool { for attr in attrs { if attr.check_name("must_use") { let mut msg = "unused result which must be used".to_string(); @@ -1046,7 +1059,7 @@ declare_lint! { pub struct NonCamelCaseTypes; impl NonCamelCaseTypes { - fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { + fn check_case(&self, cx: &LateContext, sort: &str, ident: ast::Ident, span: Span) { fn is_camel_case(ident: ast::Ident) -> bool { let ident = ident.name.as_str(); if ident.is_empty() { @@ -1087,8 +1100,10 @@ impl LintPass for NonCamelCaseTypes { fn get_lints(&self) -> LintArray { lint_array!(NON_CAMEL_CASE_TYPES) } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl LateLintPass for NonCamelCaseTypes { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { let extern_repr_count = it.attrs.iter().filter(|attr| { attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter() .any(|r| r == &attr::ReprExtern) @@ -1119,7 +1134,7 @@ impl LintPass for NonCamelCaseTypes { } } - fn check_generics(&mut self, cx: &Context, it: &hir::Generics) { + fn check_generics(&mut self, cx: &LateContext, it: &hir::Generics) { for gen in it.ty_params.iter() { self.check_case(cx, "type parameter", gen.ident, gen.span); } @@ -1127,21 +1142,21 @@ impl LintPass for NonCamelCaseTypes { } #[derive(PartialEq)] -enum MethodContext { +enum MethodLateContext { TraitDefaultImpl, TraitImpl, PlainImpl } -fn method_context(cx: &Context, id: ast::NodeId, span: Span) -> MethodContext { +fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext { match cx.tcx.impl_or_trait_items.borrow().get(&DefId::local(id)) { None => cx.sess().span_bug(span, "missing method descriptor?!"), Some(item) => match item.container() { - ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, + ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl, ty::ImplContainer(cid) => { match cx.tcx.impl_trait_ref(cid) { - Some(_) => MethodContext::TraitImpl, - None => MethodContext::PlainImpl + Some(_) => MethodLateContext::TraitImpl, + None => MethodLateContext::PlainImpl } } } @@ -1190,7 +1205,7 @@ impl NonSnakeCase { words.join("_") } - fn check_snake_case(&self, cx: &Context, sort: &str, name: &str, span: Option) { + fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option) { fn is_snake_case(ident: &str) -> bool { if ident.is_empty() { return true; @@ -1233,8 +1248,10 @@ impl LintPass for NonSnakeCase { fn get_lints(&self) -> LintArray { lint_array!(NON_SNAKE_CASE) } +} - fn check_crate(&mut self, cx: &Context, cr: &hir::Crate) { +impl LateLintPass for NonSnakeCase { + fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) { let attr_crate_name = cr.attrs.iter().find(|at| at.check_name("crate_name")) .and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref name) = cx.tcx.sess.opts.crate_name { @@ -1244,15 +1261,15 @@ impl LintPass for NonSnakeCase { } } - fn check_fn(&mut self, cx: &Context, + fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) { match fk { FnKind::Method(ident, _, _) => match method_context(cx, id, span) { - MethodContext::PlainImpl => { + MethodLateContext::PlainImpl => { self.check_snake_case(cx, "method", &ident.name.as_str(), Some(span)) }, - MethodContext::TraitDefaultImpl => { + MethodLateContext::TraitDefaultImpl => { self.check_snake_case(cx, "trait method", &ident.name.as_str(), Some(span)) }, _ => (), @@ -1264,25 +1281,25 @@ impl LintPass for NonSnakeCase { } } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemMod(_) = it.node { self.check_snake_case(cx, "module", &it.ident.name.as_str(), Some(it.span)); } } - fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { if let hir::MethodTraitItem(_, None) = trait_item.node { self.check_snake_case(cx, "trait method", &trait_item.ident.name.as_str(), Some(trait_item.span)); } } - fn check_lifetime_def(&mut self, cx: &Context, t: &hir::LifetimeDef) { + fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) { self.check_snake_case(cx, "lifetime", &t.lifetime.name.as_str(), Some(t.lifetime.span)); } - fn check_pat(&mut self, cx: &Context, p: &hir::Pat) { + fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { if let &hir::PatIdent(_, ref path1, _) = &p.node { let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); if let Some(def::DefLocal(_)) = def { @@ -1291,7 +1308,7 @@ impl LintPass for NonSnakeCase { } } - fn check_struct_def(&mut self, cx: &Context, s: &hir::StructDef, + fn check_struct_def(&mut self, cx: &LateContext, s: &hir::StructDef, _: ast::Ident, _: &hir::Generics, _: ast::NodeId) { for sf in &s.fields { if let hir::StructField_ { kind: hir::NamedField(ident, _), .. } = sf.node { @@ -1312,7 +1329,7 @@ declare_lint! { pub struct NonUpperCaseGlobals; impl NonUpperCaseGlobals { - fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) { + fn check_upper_case(cx: &LateContext, sort: &str, ident: ast::Ident, span: Span) { let s = ident.name.as_str(); if s.chars().any(|c| c.is_lowercase()) { @@ -1334,8 +1351,10 @@ impl LintPass for NonUpperCaseGlobals { fn get_lints(&self) -> LintArray { lint_array!(NON_UPPER_CASE_GLOBALS) } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl LateLintPass for NonUpperCaseGlobals { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { // only check static constants hir::ItemStatic(_, hir::MutImmutable, _) => { @@ -1348,7 +1367,7 @@ impl LintPass for NonUpperCaseGlobals { } } - fn check_trait_item(&mut self, cx: &Context, ti: &hir::TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) { match ti.node { hir::ConstTraitItem(..) => { NonUpperCaseGlobals::check_upper_case(cx, "associated constant", @@ -1358,7 +1377,7 @@ impl LintPass for NonUpperCaseGlobals { } } - fn check_impl_item(&mut self, cx: &Context, ii: &hir::ImplItem) { + fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) { match ii.node { hir::ConstImplItem(..) => { NonUpperCaseGlobals::check_upper_case(cx, "associated constant", @@ -1368,7 +1387,7 @@ impl LintPass for NonUpperCaseGlobals { } } - fn check_pat(&mut self, cx: &Context, p: &hir::Pat) { + fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { // Lint for constants that look like binding identifiers (#7526) match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) { (&hir::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => { @@ -1390,9 +1409,9 @@ declare_lint! { pub struct UnusedParens; impl UnusedParens { - fn check_unused_parens_core(&self, cx: &Context, value: &hir::Expr, msg: &str, + fn check_unused_parens_core(&self, cx: &EarlyContext, value: &ast::Expr, msg: &str, struct_lit_needs_parens: bool) { - if let hir::ExprParen(ref inner) = value.node { + if let ast::ExprParen(ref inner) = value.node { let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); if !necessary { cx.span_lint(UNUSED_PARENS, value.span, @@ -1405,27 +1424,27 @@ impl UnusedParens { /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X { /// y: 1 }) == foo` does not. - fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { + fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { match value.node { - hir::ExprStruct(..) => true, + ast::ExprStruct(..) => true, - hir::ExprAssign(ref lhs, ref rhs) | - hir::ExprAssignOp(_, ref lhs, ref rhs) | - hir::ExprBinary(_, ref lhs, ref rhs) => { + ast::ExprAssign(ref lhs, ref rhs) | + ast::ExprAssignOp(_, ref lhs, ref rhs) | + ast::ExprBinary(_, ref lhs, ref rhs) => { // X { y: 1 } + X { y: 2 } contains_exterior_struct_lit(&**lhs) || contains_exterior_struct_lit(&**rhs) } - hir::ExprUnary(_, ref x) | - hir::ExprCast(ref x, _) | - hir::ExprField(ref x, _) | - hir::ExprTupField(ref x, _) | - hir::ExprIndex(ref x, _) => { + ast::ExprUnary(_, ref x) | + ast::ExprCast(ref x, _) | + ast::ExprField(ref x, _) | + ast::ExprTupField(ref x, _) | + ast::ExprIndex(ref x, _) => { // &X { y: 1 }, X { y: 1 }.y contains_exterior_struct_lit(&**x) } - hir::ExprMethodCall(_, _, ref exprs) => { + ast::ExprMethodCall(_, _, ref exprs) => { // X { y: 1 }.bar(...) contains_exterior_struct_lit(&*exprs[0]) } @@ -1440,29 +1459,31 @@ impl LintPass for UnusedParens { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_PARENS) } +} - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { +impl EarlyLintPass for UnusedParens { + fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) { let (value, msg, struct_lit_needs_parens) = match e.node { - hir::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), - hir::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), - hir::ExprMatch(ref head, _, source) => match source { - hir::MatchSource::Normal => (head, "`match` head expression", true), - hir::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true), - hir::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true), - hir::MatchSource::ForLoopDesugar => (head, "`for` head expression", true), + ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), + ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), + ast::ExprMatch(ref head, _, source) => match source { + ast::MatchSource::Normal => (head, "`match` head expression", true), + ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true), + ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true), + ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true), }, - hir::ExprRet(Some(ref value)) => (value, "`return` value", false), - hir::ExprAssign(_, ref value) => (value, "assigned value", false), - hir::ExprAssignOp(_, _, ref value) => (value, "assigned value", false), + ast::ExprRet(Some(ref value)) => (value, "`return` value", false), + ast::ExprAssign(_, ref value) => (value, "assigned value", false), + ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false), _ => return }; self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens); } - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { let (value, msg) = match s.node { - hir::StmtDecl(ref decl, _) => match decl.node { - hir::DeclLocal(ref local) => match local.init { + ast::StmtDecl(ref decl, _) => match decl.node { + ast::DeclLocal(ref local) => match local.init { Some(ref value) => (value, "assigned value"), None => return }, @@ -1487,8 +1508,10 @@ impl LintPass for UnusedImportBraces { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_IMPORT_BRACES) } +} - fn check_item(&mut self, cx: &Context, item: &hir::Item) { +impl LateLintPass for UnusedImportBraces { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if let hir::ItemUse(ref view_path) = item.node { if let hir::ViewPathList(_, ref items) = view_path.node { if items.len() == 1 { @@ -1517,8 +1540,10 @@ impl LintPass for NonShorthandFieldPatterns { fn get_lints(&self) -> LintArray { lint_array!(NON_SHORTHAND_FIELD_PATTERNS) } +} - fn check_pat(&mut self, cx: &Context, pat: &hir::Pat) { +impl LateLintPass for NonShorthandFieldPatterns { + fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) { let def_map = cx.tcx.def_map.borrow(); if let hir::PatStruct(_, ref v, _) = pat.node { let field_pats = v.iter().filter(|fieldpat| { @@ -1556,8 +1581,10 @@ impl LintPass for UnusedUnsafe { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_UNSAFE) } +} - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { +impl LateLintPass for UnusedUnsafe { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprBlock(ref blk) = e.node { // Don't warn about generated blocks, that'll just pollute the output. if blk.rules == hir::UnsafeBlock(hir::UserProvided) && @@ -1581,8 +1608,10 @@ impl LintPass for UnsafeCode { fn get_lints(&self) -> LintArray { lint_array!(UNSAFE_CODE) } +} - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { +impl LateLintPass for UnsafeCode { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprBlock(ref blk) = e.node { // Don't warn about generated blocks, that'll just pollute the output. if blk.rules == hir::UnsafeBlock(hir::UserProvided) { @@ -1591,7 +1620,7 @@ impl LintPass for UnsafeCode { } } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemTrait(hir::Unsafety::Unsafe, _, _, _) => cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"), @@ -1603,7 +1632,7 @@ impl LintPass for UnsafeCode { } } - fn check_fn(&mut self, cx: &Context, fk: FnKind, _: &hir::FnDecl, + fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl, _: &hir::Block, span: Span, _: ast::NodeId) { match fk { FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, _, _, _) => @@ -1619,7 +1648,7 @@ impl LintPass for UnsafeCode { } } - fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { if let hir::MethodTraitItem(ref sig, None) = trait_item.node { if sig.unsafety == hir::Unsafety::Unsafe { cx.span_lint(UNSAFE_CODE, trait_item.span, @@ -1639,7 +1668,7 @@ declare_lint! { pub struct UnusedMut; impl UnusedMut { - fn check_unused_mut_pat(&self, cx: &Context, pats: &[P]) { + fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P]) { // collect all mutable pattern and group their NodeIDs by their Identifier to // avoid false warnings in match arms with multiple patterns @@ -1672,8 +1701,10 @@ impl LintPass for UnusedMut { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_MUT) } +} - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { +impl LateLintPass for UnusedMut { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprMatch(_, ref arms, _) = e.node { for a in arms { self.check_unused_mut_pat(cx, &a.pats) @@ -1681,7 +1712,7 @@ impl LintPass for UnusedMut { } } - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { if let hir::StmtDecl(ref d, _) = s.node { if let hir::DeclLocal(ref l) = d.node { self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat)); @@ -1689,7 +1720,7 @@ impl LintPass for UnusedMut { } } - fn check_fn(&mut self, cx: &Context, + fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { for a in &decl.inputs { @@ -1711,8 +1742,10 @@ impl LintPass for UnusedAllocation { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_ALLOCATION) } +} - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { +impl LateLintPass for UnusedAllocation { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnUniq, _) => (), _ => return @@ -1774,7 +1807,7 @@ impl MissingDoc { } fn check_missing_docs_attrs(&self, - cx: &Context, + cx: &LateContext, id: Option, attrs: &[ast::Attribute], sp: Span, @@ -1816,8 +1849,10 @@ impl LintPass for MissingDoc { fn get_lints(&self) -> LintArray { lint_array!(MISSING_DOCS) } +} - fn enter_lint_attrs(&mut self, _: &Context, attrs: &[ast::Attribute]) { +impl LateLintPass for MissingDoc { + fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { attr.check_name("doc") && match attr.meta_item_list() { None => false, @@ -1827,26 +1862,26 @@ impl LintPass for MissingDoc { self.doc_hidden_stack.push(doc_hidden); } - fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { + fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } - fn check_struct_def(&mut self, _: &Context, _: &hir::StructDef, + fn check_struct_def(&mut self, _: &LateContext, _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, id: ast::NodeId) { self.struct_def_stack.push(id); } - fn check_struct_def_post(&mut self, _: &Context, _: &hir::StructDef, + fn check_struct_def_post(&mut self, _: &LateContext, _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, id: ast::NodeId) { let popped = self.struct_def_stack.pop().expect("empty struct_def_stack"); assert!(popped == id); } - fn check_crate(&mut self, cx: &Context, krate: &hir::Crate) { + fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) { self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate"); } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { let desc = match it.node { hir::ItemFn(..) => "a function", hir::ItemMod(..) => "a module", @@ -1886,7 +1921,7 @@ impl LintPass for MissingDoc { self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc); } - fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { if self.private_traits.contains(&trait_item.id) { return } let desc = match trait_item.node { @@ -1900,9 +1935,9 @@ impl LintPass for MissingDoc { trait_item.span, desc); } - fn check_impl_item(&mut self, cx: &Context, impl_item: &hir::ImplItem) { + fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) { // If the method is an impl for a trait, don't doc. - if method_context(cx, impl_item.id, impl_item.span) == MethodContext::TraitImpl { + if method_context(cx, impl_item.id, impl_item.span) == MethodLateContext::TraitImpl { return; } @@ -1916,7 +1951,7 @@ impl LintPass for MissingDoc { impl_item.span, desc); } - fn check_struct_field(&mut self, cx: &Context, sf: &hir::StructField) { + fn check_struct_field(&mut self, cx: &LateContext, sf: &hir::StructField) { if let hir::NamedField(_, vis) = sf.node.kind { if vis == hir::Public || self.in_variant { let cur_struct_def = *self.struct_def_stack.last() @@ -1928,13 +1963,13 @@ impl LintPass for MissingDoc { } } - fn check_variant(&mut self, cx: &Context, v: &hir::Variant, _: &hir::Generics) { + fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) { self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs, v.span, "a variant"); assert!(!self.in_variant); self.in_variant = true; } - fn check_variant_post(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) { + fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { assert!(self.in_variant); self.in_variant = false; } @@ -1953,8 +1988,10 @@ impl LintPass for MissingCopyImplementations { fn get_lints(&self) -> LintArray { lint_array!(MISSING_COPY_IMPLEMENTATIONS) } +} - fn check_item(&mut self, cx: &Context, item: &hir::Item) { +impl LateLintPass for MissingCopyImplementations { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; } @@ -2015,8 +2052,10 @@ impl LintPass for MissingDebugImplementations { fn get_lints(&self) -> LintArray { lint_array!(MISSING_DEBUG_IMPLEMENTATIONS) } +} - fn check_item(&mut self, cx: &Context, item: &hir::Item) { +impl LateLintPass for MissingDebugImplementations { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; } @@ -2066,7 +2105,7 @@ declare_lint! { pub struct Stability; impl Stability { - fn lint(&self, cx: &Context, _id: DefId, + fn lint(&self, cx: &LateContext, _id: DefId, span: Span, stability: &Option<&attr::Stability>) { // Deprecated attributes apply in-crate and cross-crate. let (lint, label) = match *stability { @@ -2077,7 +2116,7 @@ impl Stability { output(cx, span, stability, lint, label); - fn output(cx: &Context, span: Span, stability: &Option<&attr::Stability>, + fn output(cx: &LateContext, span: Span, stability: &Option<&attr::Stability>, lint: &'static Lint, label: &'static str) { let msg = match *stability { Some(&attr::Stability { reason: Some(ref s), .. }) => { @@ -2109,29 +2148,31 @@ impl LintPass for Stability { fn get_lints(&self) -> LintArray { lint_array!(DEPRECATED) } +} - fn check_item(&mut self, cx: &Context, item: &hir::Item) { +impl LateLintPass for Stability { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { stability::check_item(cx.tcx, item, false, &mut |id, sp, stab| self.lint(cx, id, sp, &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { stability::check_expr(cx.tcx, e, &mut |id, sp, stab| self.lint(cx, id, sp, &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } - fn check_path(&mut self, cx: &Context, path: &hir::Path, id: ast::NodeId) { + fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) { stability::check_path(cx.tcx, path, id, &mut |id, sp, stab| self.lint(cx, id, sp, &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } - fn check_pat(&mut self, cx: &Context, pat: &hir::Pat) { + fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) { stability::check_pat(cx.tcx, pat, &mut |id, sp, stab| self.lint(cx, id, sp, @@ -2153,8 +2194,10 @@ impl LintPass for UnconditionalRecursion { fn get_lints(&self) -> LintArray { lint_array![UNCONDITIONAL_RECURSION] } +} - fn check_fn(&mut self, cx: &Context, fn_kind: FnKind, _: &hir::FnDecl, +impl LateLintPass for UnconditionalRecursion { + fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl, blk: &hir::Block, sp: Span, id: ast::NodeId) { type F = for<'tcx> fn(&ty::ctxt<'tcx>, ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool; @@ -2400,8 +2443,10 @@ impl LintPass for PluginAsLibrary { fn get_lints(&self) -> LintArray { lint_array![PLUGIN_AS_LIBRARY] } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl LateLintPass for PluginAsLibrary { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if cx.sess().plugin_registrar_fn.get().is_some() { // We're compiling a plugin; it's fine to link other plugins. return; @@ -2456,8 +2501,10 @@ impl LintPass for InvalidNoMangleItems { PRIVATE_NO_MANGLE_STATICS, NO_MANGLE_CONST_ITEMS) } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl LateLintPass for InvalidNoMangleItems { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) => { if attr::contains_name(&it.attrs, "no_mangle") && @@ -2502,8 +2549,10 @@ impl LintPass for MutableTransmutes { fn get_lints(&self) -> LintArray { lint_array!(MUTABLE_TRANSMUTES) } +} - fn check_expr(&mut self, cx: &Context, expr: &hir::Expr) { +impl LateLintPass for MutableTransmutes { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { use syntax::abi::RustIntrinsic; let msg = "mutating transmuted &mut T from &T may cause undefined behavior,\ @@ -2518,7 +2567,7 @@ impl LintPass for MutableTransmutes { _ => () } - fn get_transmute_from_to<'a, 'tcx>(cx: &Context<'a, 'tcx>, expr: &hir::Expr) + fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> { match expr.node { hir::ExprPath(..) => (), @@ -2542,7 +2591,7 @@ impl LintPass for MutableTransmutes { None } - fn def_id_is_transmute(cx: &Context, def_id: DefId) -> bool { + fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool { match cx.tcx.lookup_item_type(def_id).ty.sty { ty::TyBareFn(_, ref bfty) if bfty.abi == RustIntrinsic => (), _ => return false @@ -2569,7 +2618,10 @@ impl LintPass for UnstableFeatures { fn get_lints(&self) -> LintArray { lint_array!(UNSTABLE_FEATURES) } - fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) { +} + +impl LateLintPass for UnstableFeatures { + fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) { if attr::contains_name(&[attr.node.value.clone()], "feature") { if let Some(items) = attr.node.value.meta_item_list() { for item in items { @@ -2595,7 +2647,10 @@ impl LintPass for DropWithReprExtern { fn get_lints(&self) -> LintArray { lint_array!(DROP_WITH_REPR_EXTERN) } - fn check_crate(&mut self, ctx: &Context, _: &hir::Crate) { +} + +impl LateLintPass for DropWithReprExtern { + fn check_crate(&mut self, ctx: &LateContext, _: &hir::Crate) { for dtor_did in ctx.tcx.destructors.borrow().iter() { let (drop_impl_did, dtor_self_type) = if dtor_did.is_local() { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 517a3d13ddf76..5338316406063 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -67,7 +67,15 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { macro_rules! add_builtin { ($sess:ident, $($name:ident),*,) => ( {$( - store.register_pass($sess, false, box builtin::$name); + store.register_late_pass($sess, false, box builtin::$name); + )*} + ) + } + + macro_rules! add_early_builtin { + ($sess:ident, $($name:ident),*,) => ( + {$( + store.register_early_pass($sess, false, box builtin::$name); )*} ) } @@ -75,7 +83,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { macro_rules! add_builtin_with_new { ($sess:ident, $($name:ident),*,) => ( {$( - store.register_pass($sess, false, box builtin::$name::new()); + store.register_late_pass($sess, false, box builtin::$name::new()); )*} ) } @@ -86,6 +94,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { ) } + add_early_builtin!(sess, + UnusedParens, + ); + add_builtin!(sess, HardwiredLints, WhileTrue, @@ -97,7 +109,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { NonCamelCaseTypes, NonSnakeCase, NonUpperCaseGlobals, - UnusedParens, UnusedImportBraces, NonShorthandFieldPatterns, UnusedUnsafe, @@ -130,7 +141,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UNUSED_UNSAFE, PATH_STATEMENTS); // We have one lint pass defined specially - store.register_pass(sess, false, box lint::GatherNodeLevels); + store.register_late_pass(sess, false, box lint::GatherNodeLevels); // Insert temporary renamings for a one-time deprecation store.register_renamed("raw_pointer_deriving", "raw_pointer_derive"); diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index a6d06c447a4c0..5d20fe4bab4fd 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -33,9 +33,6 @@ impl Builder { ExprKind::Scope { extent: _, value } => { return this.as_constant(value); } - ExprKind::Paren { arg } => { - return this.as_constant(arg); - } ExprKind::Literal { literal } => { ConstantKind::Literal(literal) } diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index 0ceafcc9a6266..ffbb9781bdce5 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -43,9 +43,6 @@ impl Builder { this.as_lvalue(block, value) }) } - ExprKind::Paren { arg } => { - this.as_lvalue(block, arg) - } ExprKind::Field { lhs, name } => { let lvalue = unpack!(block = this.as_lvalue(block, lhs)); let lvalue = lvalue.field(name); diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index ee090571b7cc5..0b236f3a1dcc3 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -39,16 +39,10 @@ impl Builder { block, expr); let this = self; - match expr.kind { - ExprKind::Scope { extent, value } => { - return this.in_scope(extent, block, |this| { - this.as_operand(block, value) - }); - } - ExprKind::Paren { arg } => { - return this.as_operand(block, arg); - } - _ => { } + if let ExprKind::Scope { extent, value } = expr.kind { + return this.in_scope(extent, block, |this| { + this.as_operand(block, value) + }); } let category = Category::of(&expr.kind).unwrap(); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index e4d3ad21503ed..d03028ffea675 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -46,9 +46,6 @@ impl Builder { this.as_rvalue(block, value) }) } - ExprKind::Paren { arg } => { - this.as_rvalue(block, arg) - } ExprKind::InlineAsm { asm } => { block.and(Rvalue::InlineAsm(asm)) } diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 50f04e0177b0b..cb652c8a5945e 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -37,16 +37,10 @@ impl Builder { block, expr); let this = self; - match expr.kind { - ExprKind::Scope { extent, value } => { - return this.in_scope(extent, block, |this| { - this.as_temp(block, value) - }); - } - ExprKind::Paren { arg } => { - return this.as_temp(block, arg); - } - _ => { } + if let ExprKind::Scope { extent, value } = expr.kind { + return this.in_scope(extent, block, |this| { + this.as_temp(block, value) + }); } let expr_ty = expr.ty.clone(); diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 1f9928acdc81b..9cab2976b2c61 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -43,9 +43,7 @@ pub enum RvalueFunc { impl Category { pub fn of(ek: &ExprKind) -> Option { match *ek { - ExprKind::Scope { .. } | - ExprKind::Paren { .. } => - None, + ExprKind::Scope { .. } => None, ExprKind::Field { .. } | ExprKind::Deref { .. } | diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index b409903ad7eb5..72e505f2b6edd 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -40,9 +40,6 @@ impl Builder { this.into(destination, block, value) }) } - ExprKind::Paren { arg } => { - this.into(destination, block, arg) - } ExprKind::Block { body: ast_block } => { this.ast_block(destination, block, ast_block) } diff --git a/src/librustc_mir/hair.rs b/src/librustc_mir/hair.rs index c63a034833712..f1450522dd83e 100644 --- a/src/librustc_mir/hair.rs +++ b/src/librustc_mir/hair.rs @@ -171,7 +171,6 @@ pub struct Expr { #[derive(Clone, Debug)] pub enum ExprKind { Scope { extent: H::CodeExtent, value: ExprRef }, - Paren { arg: ExprRef }, // ugh. should be able to remove this! Box { place: Option>, value: ExprRef }, Call { fun: ExprRef, args: Vec> }, Deref { arg: ExprRef }, // NOT overloaded! diff --git a/src/librustc_mir/tcx/expr.rs b/src/librustc_mir/tcx/expr.rs index 350253c5b533a..7e68993b1309b 100644 --- a/src/librustc_mir/tcx/expr.rs +++ b/src/librustc_mir/tcx/expr.rs @@ -267,8 +267,6 @@ impl<'a,'tcx:'a> Mirror> for &'tcx hir::Expr { // Now comes the rote stuff: - hir::ExprParen(ref p) => - ExprKind::Paren { arg: p.to_ref() }, hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat { value: v.to_ref(), count: c.to_ref() }, hir::ExprRet(ref v) => diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 48efd34e21220..0384e7b693245 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1075,20 +1075,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { instead"); } - hir::ItemEnum(ref def, _) => { - for v in &def.variants { - match v.node.vis { - hir::Public => { - if item.vis == hir::Public { - span_err!(tcx.sess, v.span, E0448, - "unnecessary `pub` visibility"); - } - } - hir::Inherited => {} - } - } - } - + hir::ItemEnum(..) | hir::ItemTrait(..) | hir::ItemDefaultImpl(..) | hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemStruct(..) | hir::ItemFn(..) | hir::ItemMod(..) | hir::ItemTy(..) | @@ -1131,14 +1118,10 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { check_inherited(tcx, i.span, i.vis); } } - hir::ItemEnum(ref def, _) => { - for v in &def.variants { - check_inherited(tcx, v.span, v.node.vis); - } - } hir::ItemStruct(ref def, _) => check_struct(&**def), + hir::ItemEnum(..) | hir::ItemExternCrate(_) | hir::ItemUse(_) | hir::ItemTrait(..) | hir::ItemDefaultImpl(..) | hir::ItemStatic(..) | hir::ItemConst(..) | diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 83e33ede6f23f..f1997054fa394 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -542,7 +542,11 @@ fn link_binary_output(sess: &Session, } } - let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir"); + let tmpdir = match TempDir::new("rustc") { + Ok(tmpdir) => tmpdir, + Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)), + }; + match crate_type { config::CrateTypeRlib => { link_rlib(sess, Some(trans), &objects, &out_filename, diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 62b2f2949fab6..9f50e7a1e6d9a 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -1097,7 +1097,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { self.visit_expr(&**sub_ex); - let hir_node = self.tcx.map.expect_expr(sub_ex.id); + let hir_node = lower_expr(sub_ex); let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty; match *ty { ty::TyStruct(def, _) => { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 9c6f1a0eb5a89..afd16bea6d752 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -18,7 +18,7 @@ use std::path::{Path, PathBuf}; use rustc_front; use rustc::front::map::NodeItem; -use rustc_front::hir; +use rustc_front::{hir, lowering}; use syntax::attr; use syntax::ast::{self, NodeId}; @@ -442,7 +442,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_expr_data(&self, expr: &ast::Expr) -> Option { match expr.node { ast::ExprField(ref sub_ex, ident) => { - let hir_node = self.tcx.map.expect_expr(sub_ex.id); + let hir_node = lowering::lower_expr(sub_ex); let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty; match *ty { ty::TyStruct(def, _) => { @@ -462,8 +462,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } ast::ExprStruct(ref path, _, _) => { - let hir_node = self.tcx.map.expect_expr(expr.id); - let ty = &self.tcx.expr_ty_adjusted(hir_node).sty; + let hir_node = lowering::lower_expr(expr); + let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty; match *ty { ty::TyStruct(def, _) => { let sub_span = self.span_utils.span_for_last_ident(path.span); diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 0f06e3cbfa422..1d0c5137eceaa 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -703,7 +703,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let mut cur = sub; loop { match cur.node { - hir::ExprParen(ref sub) => cur = sub, hir::ExprBlock(ref blk) => { if let Some(ref sub) = blk.expr { cur = sub; @@ -830,7 +829,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let mut callee = &**callee; loop { callee = match callee.node { - hir::ExprParen(ref inner) => &**inner, hir::ExprBlock(ref block) => match block.expr { Some(ref tail) => &**tail, None => break, @@ -870,7 +868,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, const_fn_call(cx, MethodCallKey(method_call), method_did, &arg_vals, param_substs) }, - hir::ExprParen(ref e) => const_expr(cx, &**e, param_substs, fn_args).0, hir::ExprBlock(ref block) => { match block.expr { Some(ref expr) => const_expr(cx, &**expr, param_substs, fn_args).0, diff --git a/src/librustc_trans/trans/debuginfo/create_scope_map.rs b/src/librustc_trans/trans/debuginfo/create_scope_map.rs index ca616b5622a64..828086800499a 100644 --- a/src/librustc_trans/trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/trans/debuginfo/create_scope_map.rs @@ -322,8 +322,7 @@ fn walk_expr(cx: &CrateContext, hir::ExprCast(ref sub_exp, _) | hir::ExprAddrOf(_, ref sub_exp) | hir::ExprField(ref sub_exp, _) | - hir::ExprTupField(ref sub_exp, _) | - hir::ExprParen(ref sub_exp) => + hir::ExprTupField(ref sub_exp, _) => walk_expr(cx, &**sub_exp, scope_stack, scope_map), hir::ExprBox(ref place, ref sub_expr) => { diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 55c833b7686d8..370e5667c1fef 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -119,7 +119,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); - if bcx.tcx().tables.borrow().adjustments.contains_key(&expr.id) { + if adjustment_required(bcx, expr) { // use trans, which may be less efficient but // which will perform the adjustments: let datum = unpack_datum!(bcx, trans(bcx, expr)); @@ -334,6 +334,37 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, } } +fn adjustment_required<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + expr: &hir::Expr) -> bool { + let adjustment = match bcx.tcx().tables.borrow().adjustments.get(&expr.id).cloned() { + None => { return false; } + Some(adj) => adj + }; + + // Don't skip a conversion from Box to &T, etc. + if bcx.tcx().is_overloaded_autoderef(expr.id, 0) { + return true; + } + + match adjustment { + AdjustReifyFnPointer => { + // FIXME(#19925) once fn item types are + // zero-sized, we'll need to return true here + false + } + AdjustUnsafeFnPointer => { + // purely a type-level thing + false + } + AdjustDerefRef(ref adj) => { + // We are a bit paranoid about adjustments and thus might have a re- + // borrow here which merely derefs and then refs again (it might have + // a different region or mutability, but we don't care here). + !(adj.autoderefs == 1 && adj.autoref.is_some() && adj.unsize.is_none()) + } + } +} + /// Helper for trans that apply adjustments from `expr` to `datum`, which should be the unadjusted /// translation of `expr`. fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, @@ -533,7 +564,7 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Rvalue::new(ByRef))); } else { // Otherwise, simply copy the data from the source. - assert_eq!(src_ty, target_ty); + assert!(src_ty.is_phantom_data() || src_ty == target_ty); memcpy_ty(bcx, ll_target, ll_source, src_ty); } } @@ -630,9 +661,6 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_datum_unadjusted"); match expr.node { - hir::ExprParen(ref e) => { - trans(bcx, &**e) - } hir::ExprPath(..) => { trans_def(bcx, expr, bcx.def(expr.id)) } @@ -934,9 +962,6 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); match expr.node { - hir::ExprParen(ref e) => { - trans_into(bcx, &**e, Ignore) - } hir::ExprBreak(label_opt) => { controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node)) } @@ -1050,9 +1075,6 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); match expr.node { - hir::ExprParen(ref e) => { - trans_into(bcx, &**e, dest) - } hir::ExprPath(..) => { trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest) } @@ -2750,7 +2772,5 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind { ExprKind::RvalueDps } } - - hir::ExprParen(ref e) => expr_kind(tcx, &**e), } } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 69efaa792fe05..30b4cd01ade20 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -110,6 +110,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { a, b); + if a == b { + return Ok(None); + } + // Consider coercing the subtype to a DST let unsize = self.unpack_actual_value(a, |a| { self.coerce_unsized(a, b) diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 572ba7a848713..abdcbf099a57a 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -468,7 +468,6 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { loop { let last = exprs[exprs.len() - 1]; match last.node { - hir::ExprParen(ref expr) | hir::ExprField(ref expr, _) | hir::ExprTupField(ref expr, _) | hir::ExprIndex(ref expr, _) | diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 51eee67df96ec..6f1e2e283e7a2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1473,14 +1473,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => return None }; - if let ty::VariantKind::Dict = variant.kind() { + let var_kind = variant.kind(); + if var_kind == ty::VariantKind::Dict || var_kind == ty::VariantKind::Unit { Some((adt, variant)) } else { None } } - pub fn write_nil(&self, node_id: ast::NodeId) { self.write_ty(node_id, self.tcx().mk_nil()); } @@ -3444,13 +3444,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); } - hir::ExprParen(ref a) => { - check_expr_with_expectation_and_lvalue_pref(fcx, - &**a, - expected, - lvalue_pref); - fcx.write_ty(id, fcx.expr_ty(&**a)); - } hir::ExprAssign(ref lhs, ref rhs) => { check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 9ba6f1398e471..d5164af56b357 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -480,9 +480,16 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { let fields = &def_a.struct_variant().fields; let diff_fields = fields.iter().enumerate().filter_map(|(i, f)| { let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b)); - if infcx.sub_types(false, origin, b, a).is_ok() { + + if f.unsubst_ty().is_phantom_data() { + // Ignore PhantomData fields + None + } else if infcx.sub_types(false, origin, b, a).is_ok() { + // Ignore fields that aren't significantly changed None } else { + // Collect up all fields that were significantly changed + // i.e. those that contain T in coerce_unsized T -> U Some((i, a, b)) } }).collect::>(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8737957c06561..7ed572d7caa7d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1850,7 +1850,7 @@ impl Clean for doctree::Variant { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - visibility: self.vis.clean(cx), + visibility: None, stability: self.stab.clean(cx), def_id: DefId::local(self.id), inner: VariantItem(Variant { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 63468dd55f8a9..d7238c827ab57 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -141,7 +141,6 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, driver::phase_3_run_analysis_passes(sess, hir_map, - &krate, &arenas, name, resolve::MakeGlobMap::No, diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 1a027a3d14636..e2286ca819a00 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -121,7 +121,6 @@ pub struct Variant { pub attrs: Vec, pub kind: hir::VariantKind, pub id: ast::NodeId, - pub vis: hir::Visibility, pub stab: Option, pub whence: Span, } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 9d84d4ea3c1a9..5b0b19b95af19 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -54,7 +54,8 @@ } function browserSupportsHistoryApi() { - return window.history && typeof window.history.pushState === "function"; + return document.location.protocol != "file:" && + window.history && typeof window.history.pushState === "function"; } function highlightSourceLines(ev) { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e3fb13d13906d..1a20a31560bd7 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -109,7 +109,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { variants: def.variants.iter().map(|v| Variant { name: v.node.name, attrs: v.node.attrs.clone(), - vis: v.node.vis, stab: self.stability(v.node.id), id: v.node.id, kind: v.node.kind.clone(), diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index a0c3f013f2b4e..a07d21add8db9 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -68,6 +68,10 @@ macro_rules! panic { /// necessary to use `io::stdout().flush()` to ensure the output is emitted /// immediately. /// +/// # Panics +/// +/// Panics if writing to `io::stdout()` fails. +/// /// # Examples /// /// ``` @@ -99,6 +103,10 @@ macro_rules! print { /// Use the `format!` syntax to write data to the standard output. /// See `std::fmt` for more information. /// +/// # Panics +/// +/// Panics if writing to `io::stdout()` fails. +/// /// # Examples /// /// ``` diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bf8c67c7ae181..58d92f5001aae 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1614,7 +1614,6 @@ pub struct Variant_ { pub id: NodeId, /// Explicit discriminant, eg `Foo = 1` pub disr_expr: Option>, - pub vis: Visibility, } pub type Variant = Spanned; diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index faf0b51c8de0e..889a0d7e440e1 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -141,7 +141,7 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ None } else { Some(v.map(|Spanned {node: ast::Variant_ {id, name, attrs, kind, - disr_expr, vis}, span}| { + disr_expr}, span}| { Spanned { node: ast::Variant_ { id: id, @@ -154,7 +154,6 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ } }, disr_expr: disr_expr, - vis: vis }, span: span } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 771ac85ef1921..f8beb0e36e2c3 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1013,7 +1013,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { kind: ast::TupleVariantKind(args), id: ast::DUMMY_NODE_ID, disr_expr: None, - vis: ast::Public }) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index abc0410295055..989977a691755 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -191,6 +191,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status // allow `#[unwind]` ("unwind_attributes", "1.4.0", None, Active), + + // allow empty structs/enum variants with braces + ("braced_empty_structs", "1.5.0", None, Active), ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -775,7 +778,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } - ast::ItemStruct(..) => { + ast::ItemStruct(ref def, _) => { if attr::contains_name(&i.attrs[..], "simd") { self.gate_feature("simd", i.span, "SIMD types are experimental and possibly buggy"); @@ -794,6 +797,10 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } } + if def.fields.is_empty() && def.ctor_id.is_none() { + self.gate_feature("braced_empty_structs", i.span, + "empty structs with braces are unstable"); + } } ast::ItemDefaultImpl(..) => { @@ -843,6 +850,12 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { "box expression syntax is experimental; \ you can call `Box::new` instead."); } + ast::ExprStruct(_, ref fields, ref expr) => { + if fields.is_empty() && expr.is_none() { + self.gate_feature("braced_empty_structs", e.span, + "empty structs with braces are unstable"); + } + } _ => {} } visit::walk_expr(self, e); @@ -867,6 +880,12 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { pattern.span, "box pattern syntax is experimental"); } + ast::PatStruct(_, ref fields, dotdot) => { + if fields.is_empty() && !dotdot { + self.gate_feature("braced_empty_structs", pattern.span, + "empty structs with braces are unstable"); + } + } _ => {} } visit::walk_pat(self, pattern) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0cfddc9857c67..a73cc420eeb04 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -450,7 +450,7 @@ pub fn noop_fold_foreign_mod(ForeignMod {abi, items}: ForeignMod, } pub fn noop_fold_variant(v: P, fld: &mut T) -> P { - v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr, vis}, span}| Spanned { + v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr}, span}| Spanned { node: Variant_ { id: fld.new_id(id), name: name, @@ -465,7 +465,6 @@ pub fn noop_fold_variant(v: P, fld: &mut T) -> P { } }, disr_expr: disr_expr.map(|e| fld.fold_expr(e)), - vis: vis, }, span: fld.new_span(span), }) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ff622859cf0b1..7f57170c2ef66 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1263,7 +1263,7 @@ impl<'a> Parser<'a> { pub fn parse_ret_ty(&mut self) -> PResult { if try!(self.eat(&token::RArrow) ){ if try!(self.eat(&token::Not) ){ - Ok(NoReturn(self.span)) + Ok(NoReturn(self.last_span)) } else { Ok(Return(try!(self.parse_ty_nopanic()))) } @@ -2231,14 +2231,6 @@ impl<'a> Parser<'a> { &[token::CloseDelim(token::Brace)])); } - if fields.is_empty() && base.is_none() { - let last_span = self.last_span; - self.span_err(last_span, - "structure literal must either \ - have at least one field or use \ - structure update syntax"); - } - hi = self.span.hi; try!(self.expect(&token::CloseDelim(token::Brace))); ex = ExprStruct(pth, fields, base); @@ -4713,14 +4705,14 @@ impl<'a> Parser<'a> { (Vec::new(), Some(ast::DUMMY_NODE_ID)) } else { // If we see: `struct Foo where T: Copy { ... }` - (try!(self.parse_record_struct_body(&class_name)), None) + (try!(self.parse_record_struct_body()), None) } // No `where` so: `struct Foo;` } else if try!(self.eat(&token::Semi) ){ (Vec::new(), Some(ast::DUMMY_NODE_ID)) // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { - let fields = try!(self.parse_record_struct_body(&class_name)); + let fields = try!(self.parse_record_struct_body()); (fields, None) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { @@ -4740,20 +4732,13 @@ impl<'a> Parser<'a> { None)) } - pub fn parse_record_struct_body(&mut self, - class_name: &ast::Ident) -> PResult> { + pub fn parse_record_struct_body(&mut self) -> PResult> { let mut fields = Vec::new(); if try!(self.eat(&token::OpenDelim(token::Brace)) ){ while self.token != token::CloseDelim(token::Brace) { fields.push(try!(self.parse_struct_decl_field(true))); } - if fields.is_empty() { - return Err(self.fatal(&format!("unit-like struct definition should be \ - written as `struct {};`", - class_name))); - } - try!(self.bump()); } else { let token_str = self.this_token_to_string(); @@ -5116,12 +5101,19 @@ impl<'a> Parser<'a> { try!(self.expect(&token::Semi)); let last_span = self.last_span; + + if visibility == ast::Public { + self.span_warn(mk_sp(lo, last_span.hi), + "`pub extern crate` does not work as expected and should not be used. \ + Likely to become an error. Prefer `extern crate` and `pub use`."); + } + Ok(self.mk_item(lo, - last_span.hi, - ident, - ItemExternCrate(maybe_path), - visibility, - attrs)) + last_span.hi, + ident, + ItemExternCrate(maybe_path), + visibility, + attrs)) } /// Parse `extern` for foreign ABIs @@ -5200,13 +5192,10 @@ impl<'a> Parser<'a> { let variant_attrs = self.parse_outer_attributes(); let vlo = self.span.lo; - let vis = try!(self.parse_visibility()); - - let ident; let kind; let mut args = Vec::new(); let mut disr_expr = None; - ident = try!(self.parse_ident()); + let ident = try!(self.parse_ident()); if try!(self.eat(&token::OpenDelim(token::Brace)) ){ // Parse a struct variant. all_nullary = false; @@ -5248,7 +5237,6 @@ impl<'a> Parser<'a> { kind: kind, id: ast::DUMMY_NODE_ID, disr_expr: disr_expr, - vis: vis, }; variants.push(P(spanned(vlo, self.last_span.hi, vr))); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b00ff85051c9a..6de6d32dfb328 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1507,7 +1507,6 @@ impl<'a> State<'a> { } pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> { - try!(self.print_visibility(v.node.vis)); match v.node.kind { ast::TupleVariantKind(ref args) => { try!(self.print_ident(v.node.name)); @@ -1855,34 +1854,34 @@ impl<'a> State<'a> { fields: &[ast::Field], wth: &Option>) -> io::Result<()> { try!(self.print_path(path, true, 0)); - if !(fields.is_empty() && wth.is_none()) { - try!(word(&mut self.s, "{")); - try!(self.commasep_cmnt( - Consistent, - &fields[..], - |s, field| { - try!(s.ibox(indent_unit)); - try!(s.print_ident(field.ident.node)); - try!(s.word_space(":")); - try!(s.print_expr(&*field.expr)); - s.end() - }, - |f| f.span)); - match *wth { - Some(ref expr) => { - try!(self.ibox(indent_unit)); - if !fields.is_empty() { - try!(word(&mut self.s, ",")); - try!(space(&mut self.s)); - } - try!(word(&mut self.s, "..")); - try!(self.print_expr(&**expr)); - try!(self.end()); + try!(word(&mut self.s, "{")); + try!(self.commasep_cmnt( + Consistent, + &fields[..], + |s, field| { + try!(s.ibox(indent_unit)); + try!(s.print_ident(field.ident.node)); + try!(s.word_space(":")); + try!(s.print_expr(&*field.expr)); + s.end() + }, + |f| f.span)); + match *wth { + Some(ref expr) => { + try!(self.ibox(indent_unit)); + if !fields.is_empty() { + try!(word(&mut self.s, ",")); + try!(space(&mut self.s)); } - _ => try!(word(&mut self.s, ",")), + try!(word(&mut self.s, "..")); + try!(self.print_expr(&**expr)); + try!(self.end()); + } + _ => if !fields.is_empty() { + try!(word(&mut self.s, ",")) } - try!(word(&mut self.s, "}")); } + try!(word(&mut self.s, "}")); Ok(()) } @@ -3139,11 +3138,10 @@ mod tests { kind: ast::TupleVariantKind(Vec::new()), id: 0, disr_expr: None, - vis: ast::Public, }); let varstr = variant_to_string(&var); - assert_eq!(varstr, "pub principal_skinner"); + assert_eq!(varstr, "principal_skinner"); } #[test] diff --git a/src/test/auxiliary/lint_for_crate.rs b/src/test/auxiliary/lint_for_crate.rs index 4c9c7f443c290..7ae161a86a361 100644 --- a/src/test/auxiliary/lint_for_crate.rs +++ b/src/test/auxiliary/lint_for_crate.rs @@ -17,7 +17,7 @@ extern crate rustc_front; extern crate syntax; -use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; use rustc::plugin::Registry; use rustc_front::hir; use syntax::attr; @@ -30,8 +30,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(CRATE_NOT_OKAY) } +} - fn check_crate(&mut self, cx: &Context, krate: &hir::Crate) { +impl LateLintPass for Pass { + fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) { if !attr::contains_name(&krate.attrs, "crate_okay") { cx.span_lint(CRATE_NOT_OKAY, krate.span, "crate is not marked with #![crate_okay]"); @@ -41,5 +43,5 @@ impl LintPass for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_lint_pass(box Pass as LintPassObject); + reg.register_late_lint_pass(box Pass as LateLintPassObject); } diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index adc194fa45486..13cf5f09db32b 100644 --- a/src/test/auxiliary/lint_group_plugin_test.rs +++ b/src/test/auxiliary/lint_group_plugin_test.rs @@ -20,7 +20,7 @@ extern crate rustc_front; extern crate rustc; use rustc_front::hir; -use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; use rustc::plugin::Registry; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); @@ -33,8 +33,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(TEST_LINT, PLEASE_LINT) } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl LateLintPass for Pass { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match &*it.ident.name.as_str() { "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), @@ -45,6 +47,6 @@ impl LintPass for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_lint_pass(box Pass as LintPassObject); + reg.register_late_lint_pass(box Pass as LateLintPassObject); reg.register_lint_group("lint_me", vec![TEST_LINT, PLEASE_LINT]); } diff --git a/src/test/auxiliary/lint_plugin_test.rs b/src/test/auxiliary/lint_plugin_test.rs index e6f91db230009..4f5e8d6e0874c 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -13,15 +13,16 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -extern crate rustc_front; +extern crate syntax; // Load rustc as a plugin to get macros #[macro_use] extern crate rustc; -use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; +use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, + EarlyLintPassObject, LintArray}; use rustc::plugin::Registry; -use rustc_front::hir; +use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); struct Pass; @@ -30,8 +31,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(TEST_LINT) } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl EarlyLintPass for Pass { + fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name == "lintme" { cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); } @@ -40,5 +43,5 @@ impl LintPass for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_lint_pass(box Pass as LintPassObject); + reg.register_early_lint_pass(box Pass as EarlyLintPassObject); } diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 232d6b414f580..21ac23253c86a 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -192,7 +192,7 @@ fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec) { i += 2; } - res.push(cur_byte^-1); + res.push(cur_byte^!0); } } diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs new file mode 100644 index 0000000000000..d9a7acf112908 --- /dev/null +++ b/src/test/codegen/adjustments.rs @@ -0,0 +1,37 @@ +// 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. + +// compile-flags: -C no-prepopulate-passes + +// Hack to get the correct size for the length part in slices +// CHECK: @helper([[USIZE:i[0-9]+]]) +#[no_mangle] +fn helper(_: usize) { +} + +// CHECK-LABEL: @no_op_slice_adjustment +#[no_mangle] +pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] { + // We used to generate an extra alloca and memcpy for the block's trailing expression value, so + // check that we copy directly to the return value slot +// CHECK: [[SRC:%[0-9]+]] = bitcast { i8*, [[USIZE]] }* %x to +// CHECK: [[DST:%[0-9]+]] = bitcast { i8*, [[USIZE]] }* %sret_slot to i8* +// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[DST]], i8* [[SRC]], + { x } +} + +// CHECK-LABEL: @no_op_slice_adjustment2 +#[no_mangle] +pub fn no_op_slice_adjustment2(x: &[u8]) -> &[u8] { + // We used to generate an extra alloca and memcpy for the function's return value, so check + // that there's no memcpy (the slice is written to sret_slot element-wise) +// CHECK-NOT: call void @llvm.memcpy. + no_op_slice_adjustment(x) +} diff --git a/src/test/compile-fail/autoderef-full-lval.rs b/src/test/compile-fail/autoderef-full-lval.rs index 2c5749e0d5d39..0d666a4920038 100644 --- a/src/test/compile-fail/autoderef-full-lval.rs +++ b/src/test/compile-fail/autoderef-full-lval.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] #![feature(box_syntax)] struct clam { diff --git a/src/test/compile-fail/borrow-tuple-fields.rs b/src/test/compile-fail/borrow-tuple-fields.rs index b1abbad525356..f3417fafe9037 100644 --- a/src/test/compile-fail/borrow-tuple-fields.rs +++ b/src/test/compile-fail/borrow-tuple-fields.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] #![feature(box_syntax)] struct Foo(Box, isize); diff --git a/src/test/compile-fail/cast-as-bool.rs b/src/test/compile-fail/cast-as-bool.rs index 92cbbaa1cb442..52a4950022d1e 100644 --- a/src/test/compile-fail/cast-as-bool.rs +++ b/src/test/compile-fail/cast-as-bool.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - let u = (5 as bool); + let u = 5 as bool; //~^ ERROR cannot cast as `bool` //~^^ HELP compare with zero instead } diff --git a/src/test/compile-fail/dropck_arr_cycle_checked.rs b/src/test/compile-fail/dropck_arr_cycle_checked.rs index 19f790ddc9071..9cfeaca6dfadf 100644 --- a/src/test/compile-fail/dropck_arr_cycle_checked.rs +++ b/src/test/compile-fail/dropck_arr_cycle_checked.rs @@ -19,7 +19,6 @@ use std::cell::Cell; use id::Id; mod s { - #![allow(unstable)] use std::sync::atomic::{AtomicUsize, Ordering}; static S_COUNT: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/compile-fail/dropck_tarena_cycle_checked.rs b/src/test/compile-fail/dropck_tarena_cycle_checked.rs index 584e5eabf0cd8..d36293a484d4e 100644 --- a/src/test/compile-fail/dropck_tarena_cycle_checked.rs +++ b/src/test/compile-fail/dropck_tarena_cycle_checked.rs @@ -16,7 +16,6 @@ // which is a reduction of this code to more directly show the reason // for the error message we see here.) -#![allow(unstable)] #![feature(const_fn)] extern crate arena; @@ -26,7 +25,6 @@ use std::cell::Cell; use id::Id; mod s { - #![allow(unstable)] use std::sync::atomic::{AtomicUsize, Ordering}; static S_COUNT: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/compile-fail/dropck_tarena_unsound_drop.rs b/src/test/compile-fail/dropck_tarena_unsound_drop.rs index 7a204e6143eef..600c794109ccf 100644 --- a/src/test/compile-fail/dropck_tarena_unsound_drop.rs +++ b/src/test/compile-fail/dropck_tarena_unsound_drop.rs @@ -19,8 +19,6 @@ // (Also compare against dropck_tarena_cycle_checked.rs, from which // this was reduced to better understand its error message.) -#![allow(unstable)] - extern crate arena; use arena::TypedArena; diff --git a/src/test/compile-fail/dropck_vec_cycle_checked.rs b/src/test/compile-fail/dropck_vec_cycle_checked.rs index bc33ff8399aa5..caf25e68d568c 100644 --- a/src/test/compile-fail/dropck_vec_cycle_checked.rs +++ b/src/test/compile-fail/dropck_vec_cycle_checked.rs @@ -18,7 +18,6 @@ use std::cell::Cell; use id::Id; mod s { - #![allow(unstable)] use std::sync::atomic::{AtomicUsize, Ordering}; static S_COUNT: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/parse-fail/struct-no-fields-4.rs b/src/test/compile-fail/empty-struct-with-braces-1.rs similarity index 59% rename from src/test/parse-fail/struct-no-fields-4.rs rename to src/test/compile-fail/empty-struct-with-braces-1.rs index 6e55baf06cedf..ad412259faa29 100644 --- a/src/test/parse-fail/struct-no-fields-4.rs +++ b/src/test/compile-fail/empty-struct-with-braces-1.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// Empty struct defined with braces shouldn't add names into value namespace -struct Foo; +#![feature(braced_empty_structs)] -fn h4() { - let _end_of_tuple = (3, Foo { }); - //~^ ERROR: structure literal must either have at least one field -} +struct Empty {} -fn main() {} +fn main() { + let e = Empty; //~ ERROR `Empty` is the name of a struct or struct variant +} diff --git a/src/test/compile-fail/empty-struct-with-braces-2.rs b/src/test/compile-fail/empty-struct-with-braces-2.rs new file mode 100644 index 0000000000000..0e72e7dc44185 --- /dev/null +++ b/src/test/compile-fail/empty-struct-with-braces-2.rs @@ -0,0 +1,25 @@ +// 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. + +// Empty struct defined with braces shouldn't add names into value namespace + +#![feature(braced_empty_structs)] +#![deny(warnings)] + +struct Empty {} + +fn main() { + let e = Empty {}; + + match e { + Empty => () //~ ERROR unused variable: `Empty` + //~^ ERROR variable `Empty` should have a snake case name such as `empty` + } +} diff --git a/src/test/compile-fail/empty-struct-with-braces-3.rs b/src/test/compile-fail/empty-struct-with-braces-3.rs new file mode 100644 index 0000000000000..e6f20ba345ad3 --- /dev/null +++ b/src/test/compile-fail/empty-struct-with-braces-3.rs @@ -0,0 +1,21 @@ +// 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. + +// Feature gate test for empty struct with braces + +struct Empty {} //~ ERROR empty structs with braces are unstable + +fn main() { + let e = Empty {}; //~ ERROR empty structs with braces are unstable + + match e { + Empty {} => {} //~ ERROR empty structs with braces are unstable + } +} diff --git a/src/test/run-pass/feature-gate-negate-unsigned.rs b/src/test/compile-fail/feature-gate-negate-unsigned.rs similarity index 67% rename from src/test/run-pass/feature-gate-negate-unsigned.rs rename to src/test/compile-fail/feature-gate-negate-unsigned.rs index 95c8e62be53bc..b1c73fab4ffa6 100644 --- a/src/test/run-pass/feature-gate-negate-unsigned.rs +++ b/src/test/compile-fail/feature-gate-negate-unsigned.rs @@ -18,21 +18,21 @@ impl std::ops::Neg for S { } const _MAX: usize = -1; -//~^ WARN unary negation of unsigned integers will be feature gated in the future +//~^ ERROR unary negation of unsigned integers may be removed in the future fn main() { let a = -1; - //~^ WARN unary negation of unsigned integers will be feature gated in the future + //~^ ERROR unary negation of unsigned integers may be removed in the future let _b : u8 = a; // for infering variable a to u8. -a; - //~^ WARN unary negation of unsigned integers will be feature gated in the future + //~^ ERROR unary negation of unsigned integers may be removed in the future let _d = -1u8; - //~^ WARN unary negation of unsigned integers will be feature gated in the future + //~^ ERROR unary negation of unsigned integers may be removed in the future for _ in -10..10u8 {} - //~^ WARN unary negation of unsigned integers will be feature gated in the future + //~^ ERROR unary negation of unsigned integers may be removed in the future -S; // should not trigger the gate; issue 26840 } diff --git a/src/test/compile-fail/for-loop-hygiene.rs b/src/test/compile-fail/for-loop-hygiene.rs index ff6f848ab598d..f06882875fd9b 100644 --- a/src/test/compile-fail/for-loop-hygiene.rs +++ b/src/test/compile-fail/for-loop-hygiene.rs @@ -11,8 +11,6 @@ // for-loops are expanded in the front end, and use an `iter` ident in their expansion. Check that // `iter` is not accessible inside the for loop. -#![allow(unstable)] - fn main() { for _ in 0..10 { iter.next(); //~ error: unresolved name `iter` diff --git a/src/test/compile-fail/issue-17283.rs b/src/test/compile-fail/issue-17283.rs index a481fec6bf968..c7d6443663241 100644 --- a/src/test/compile-fail/issue-17283.rs +++ b/src/test/compile-fail/issue-17283.rs @@ -11,6 +11,8 @@ // Test that the parser does not attempt to parse struct literals // within assignments in if expressions. +#![allow(unused_parens)] + struct Foo { foo: usize } diff --git a/src/test/compile-fail/issue-22872.rs b/src/test/compile-fail/issue-22872.rs deleted file mode 100644 index 86982284ac2c0..0000000000000 --- a/src/test/compile-fail/issue-22872.rs +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -trait Wrap<'b> { - fn foo(&'b mut self); -} - -struct Wrapper

(P); - -impl<'b, P> Wrap<'b> for Wrapper

-where P: Process<'b>, -

>::Item: Iterator { - fn foo(&mut self) {} -} - - -pub trait Process<'a> { - type Item; - fn bar(&'a self); -} - -fn push_process

(process: P) where P: Process<'static> { - let _: Box Wrap<'b>> = Box::new(Wrapper(process)); - //~^ ERROR the trait `for<'b> Process<'b>` is not implemented for the type `P` [E0277] - //~| ERROR the trait `for<'b> core::iter::Iterator` is not implemented for the type - //~| ERROR cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting -} - -fn main() {} diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index 8c83c4cefd191..dba9c32f9b480 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> } fn main() { - let ex = (|x| { + let ex = |x| { let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `_` - let_(add(x, x), |x|x)})}); + let_(add(x, x), |x|x)})}; } diff --git a/src/test/parse-fail/struct-no-fields-3.rs b/src/test/compile-fail/issue-23543.rs similarity index 66% rename from src/test/parse-fail/struct-no-fields-3.rs rename to src/test/compile-fail/issue-23543.rs index 8e72151ffe979..4ed44154c4748 100644 --- a/src/test/parse-fail/struct-no-fields-3.rs +++ b/src/test/compile-fail/issue-23543.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +pub trait A: Copy {} struct Foo; -fn g3() { - let _mid_tuple = (Foo { }, 2); - //~^ ERROR: structure literal must either have at least one field +pub trait D { + fn f(self) + where T: A; + //~^ ERROR associated type bindings are not allowed here [E0229] } fn main() {} diff --git a/src/test/parse-fail/struct-no-fields-5.rs b/src/test/compile-fail/issue-23544.rs similarity index 64% rename from src/test/parse-fail/struct-no-fields-5.rs rename to src/test/compile-fail/issue-23544.rs index 5f92d98606693..1d7c2187045ea 100644 --- a/src/test/parse-fail/struct-no-fields-5.rs +++ b/src/test/compile-fail/issue-23544.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +pub trait A: Copy {} -struct Foo; - -fn i5() { - let _end_of_block = { Foo { } }; - //~^ ERROR: structure literal must either have at least one field +pub trait D { + fn f(self) + where T: A; + //~^ ERROR associated type bindings are not allowed here [E0229] } fn main() {} diff --git a/src/test/compile-fail/issue-23729.rs b/src/test/compile-fail/issue-23729.rs index 3d77d171acebf..f98cf6575d6ec 100644 --- a/src/test/compile-fail/issue-23729.rs +++ b/src/test/compile-fail/issue-23729.rs @@ -26,7 +26,7 @@ fn main() { self.pos += 1; Some(next_val) } else { - let next_val = (self.mem[0] + self.mem[1]); + let next_val = self.mem[0] + self.mem[1]; self.mem[0] = self.mem[1]; self.mem[1] = next_val; Some(next_val) diff --git a/src/test/compile-fail/issue-26905.rs b/src/test/compile-fail/issue-26905.rs new file mode 100644 index 0000000000000..3b8fac832a464 --- /dev/null +++ b/src/test/compile-fail/issue-26905.rs @@ -0,0 +1,34 @@ +// 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. + +#![feature(unsize, coerce_unsized)] + +// Verfies that non-PhantomData ZSTs still cause coercions to fail. +// They might have additional semantics that we don't want to bulldoze. + +use std::marker::{Unsize, PhantomData}; +use std::ops::CoerceUnsized; + +struct NotPhantomData(PhantomData); + +struct MyRc { + _ptr: *const T, + _boo: NotPhantomData, +} + +impl, U: ?Sized> CoerceUnsized> for MyRc{ } //~ERROR + +fn main() { + let data = [1, 2, 3]; + let iter = data.iter(); + let x = MyRc { _ptr: &iter, _boo: NotPhantomData(PhantomData) }; + let _y: MyRc> = x; +} + diff --git a/src/test/compile-fail/issue-27831.rs b/src/test/compile-fail/issue-27831.rs index 336368cf8a49d..533387c576008 100644 --- a/src/test/compile-fail/issue-27831.rs +++ b/src/test/compile-fail/issue-27831.rs @@ -22,8 +22,8 @@ fn main() { let Foo { .. } = x; //~ ERROR `Foo` does not name a struct let x = Bar; - Bar { ..x }; //~ ERROR `Bar` does not name a structure - let Bar { .. } = x; //~ ERROR `Bar` does not name a struct + Bar { ..x }; + let Bar { .. } = x; match Enum::Bar { Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct diff --git a/src/test/compile-fail/issue-28433.rs b/src/test/compile-fail/issue-28433.rs new file mode 100644 index 0000000000000..3ca2213087d1f --- /dev/null +++ b/src/test/compile-fail/issue-28433.rs @@ -0,0 +1,21 @@ +// 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. + +enum bird { + pub duck, + //~^ ERROR: expected identifier, found keyword `pub` + //~^^ ERROR: expected + goose +} + + +fn main() { + let y = bird::goose; +} diff --git a/src/test/compile-fail/lint-visible-private-types.rs b/src/test/compile-fail/lint-visible-private-types.rs index c6dc3b70bef37..d34738282eb26 100644 --- a/src/test/compile-fail/lint-visible-private-types.rs +++ b/src/test/compile-fail/lint-visible-private-types.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(visible_private_types)] #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/compile-fail/loop-does-not-diverge.rs b/src/test/compile-fail/loop-does-not-diverge.rs index 12de4a714efc5..cd320ba148aba 100644 --- a/src/test/compile-fail/loop-does-not-diverge.rs +++ b/src/test/compile-fail/loop-does-not-diverge.rs @@ -18,5 +18,5 @@ fn forever() -> ! { } fn main() { - if (1 == 2) { forever(); } + if 1 == 2 { forever(); } } diff --git a/src/test/compile-fail/useless-priv.rs b/src/test/compile-fail/useless-pub.rs similarity index 91% rename from src/test/compile-fail/useless-priv.rs rename to src/test/compile-fail/useless-pub.rs index 59964d0df956c..fb6cdf7fa5924 100644 --- a/src/test/compile-fail/useless-priv.rs +++ b/src/test/compile-fail/useless-pub.rs @@ -9,7 +9,6 @@ // except according to those terms. struct A { pub i: isize } -pub enum C { pub Variant } //~ ERROR: unnecessary `pub` pub trait E { fn foo(&self); diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index 222d8338aa2c4..b6f197987bab1 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(bivariance)] #![allow(dead_code)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs index e407ebe345a5b..2fd8bf20c7997 100644 --- a/src/test/compile-fail/variance-types.rs +++ b/src/test/compile-fail/variance-types.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(bivariance)] #![allow(dead_code)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs index 375289596841d..c8f4326bb2824 100644 --- a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs +++ b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs @@ -29,7 +29,6 @@ use std::cell::Cell; use id::Id; mod s { - #![allow(unstable)] use std::sync::atomic::{AtomicUsize, Ordering}; static S_COUNT: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/parse-fail/struct-no-fields-2.rs b/src/test/compile-fail/warn-pub-extern-crate.rs similarity index 63% rename from src/test/parse-fail/struct-no-fields-2.rs rename to src/test/compile-fail/warn-pub-extern-crate.rs index 1e6169f285b5c..fec0b8e1a4cc1 100644 --- a/src/test/parse-fail/struct-no-fields-2.rs +++ b/src/test/compile-fail/warn-pub-extern-crate.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// Check that `pub extern crate` gives a warning. -struct Foo; -fn f2() { - let _end_stmt = Foo { }; - //~^ ERROR: structure literal must either have at least one field -} +pub extern crate core; //~WARN `pub extern crate` does not work +//~^ ERROR core -fn main() {} +fn main() { +} diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 6398c76d0a351..835f7fc96c63f 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -27,10 +27,9 @@ let _: [(); (1 as usize)] = ([(() as ())] as [(); 1]); let _ = - (((&((([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3])) as [i32; 3]) - as &[i32; 3]) as *const _ as *const [i32; 3]) as - *const [i32; (3 as usize)] as *const [i32; 3]); - + (((&([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3]) as &[i32; 3]) + as *const _ as *const [i32; 3]) as *const [i32; (3 as usize)] as + *const [i32; 3]); diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/1 b/src/test/run-make/allow-non-lint-warnings-cmdline/1 deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/test/run-make/allow-warnings-cmdline-stability/1 b/src/test/run-make/allow-warnings-cmdline-stability/1 deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/test/run-make/archive-duplicate-names/Makefile b/src/test/run-make/archive-duplicate-names/Makefile index 72c2d389e2aac..5202e6dea541e 100644 --- a/src/test/run-make/archive-duplicate-names/Makefile +++ b/src/test/run-make/archive-duplicate-names/Makefile @@ -3,8 +3,8 @@ all: mkdir $(TMPDIR)/a mkdir $(TMPDIR)/b - $(CC) -c -o $(TMPDIR)/a/foo.o foo.c - $(CC) -c -o $(TMPDIR)/b/foo.o bar.c + $(call COMPILE_OBJ,$(TMPDIR)/a/foo.o,foo.c) + $(call COMPILE_OBJ,$(TMPDIR)/b/foo.o,bar.c) ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o $(RUSTC) foo.rs $(RUSTC) bar.rs diff --git a/src/test/run-make/c-dynamic-dylib/cfoo.c b/src/test/run-make/c-dynamic-dylib/cfoo.c index 113717a776a99..a975549354123 100644 --- a/src/test/run-make/c-dynamic-dylib/cfoo.c +++ b/src/test/run-make/c-dynamic-dylib/cfoo.c @@ -1,2 +1,5 @@ // ignore-license +#ifdef _WIN32 +__declspec(dllexport) +#endif int foo() { return 0; } diff --git a/src/test/run-make/c-dynamic-rlib/cfoo.c b/src/test/run-make/c-dynamic-rlib/cfoo.c index 113717a776a99..b2849326a7588 100644 --- a/src/test/run-make/c-dynamic-rlib/cfoo.c +++ b/src/test/run-make/c-dynamic-rlib/cfoo.c @@ -1,2 +1,6 @@ // ignore-license + +#ifdef _WIN32 +__declspec(dllexport) +#endif int foo() { return 0; } diff --git a/src/test/run-make/c-link-to-rust-dylib/Makefile b/src/test/run-make/c-link-to-rust-dylib/Makefile index 2a6cc0394852e..7b2130cd4ed96 100644 --- a/src/test/run-make/c-link-to-rust-dylib/Makefile +++ b/src/test/run-make/c-link-to-rust-dylib/Makefile @@ -1,10 +1,17 @@ -include ../tools.mk -HOST_LIB_DIR=$(TMPDIR)/../../../stage$(RUST_BUILD_STAGE)/lib - -all: - $(RUSTC) foo.rs - $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(call RPATH_LINK_SEARCH,$(HOST_LIB_DIR)) -Wl,-rpath,$(TMPDIR) $(EXTRACFLAGS) +all: $(TMPDIR)/$(call BIN,bar) $(call RUN,bar) $(call REMOVE_DYLIBS,foo) $(call FAIL,bar) + +ifdef IS_MSVC +$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo) + $(CC) bar.c $(TMPDIR)/foo.lib $(call OUT_EXE,bar) +else +$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo) + $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) -L $(TMPDIR) +endif + +$(call DYLIB,foo): foo.rs + $(RUSTC) foo.rs diff --git a/src/test/run-make/c-link-to-rust-staticlib/Makefile b/src/test/run-make/c-link-to-rust-staticlib/Makefile index 2b927e3e4a730..3d44b3c256efc 100644 --- a/src/test/run-make/c-link-to-rust-staticlib/Makefile +++ b/src/test/run-make/c-link-to-rust-staticlib/Makefile @@ -1,12 +1,12 @@ -include ../tools.mk -EXTRAFLAGS := $(EXTRACFLAGS) - # FIXME: ignore freebsd ifneq ($(shell uname),FreeBSD) all: $(RUSTC) foo.rs - $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRAFLAGS) $(EXTRACXXFLAGS) + cp $(TMPDIR)/libfoo.a $(call NATIVE_STATICLIB,foo2) + $(CC) bar.c $(call NATIVE_STATICLIB,foo2) $(call OUT_EXE,bar) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) $(call RUN,bar) rm $(call STATICLIB,foo*) $(call RUN,bar) diff --git a/src/test/run-make/c-static-dylib/Makefile b/src/test/run-make/c-static-dylib/Makefile index 9914e12d5696e..f88786857ccdc 100644 --- a/src/test/run-make/c-static-dylib/Makefile +++ b/src/test/run-make/c-static-dylib/Makefile @@ -1,9 +1,9 @@ -include ../tools.mk -all: $(call STATICLIB,cfoo) +all: $(call NATIVE_STATICLIB,cfoo) $(RUSTC) foo.rs -C prefer-dynamic $(RUSTC) bar.rs - rm $(TMPDIR)/$(call STATICLIB_GLOB,cfoo) + rm $(call NATIVE_STATICLIB,cfoo) $(call RUN,bar) $(call REMOVE_DYLIBS,foo) $(call FAIL,bar) diff --git a/src/test/run-make/c-static-rlib/Makefile b/src/test/run-make/c-static-rlib/Makefile index 02b24ef9846dd..be22b2728f05b 100644 --- a/src/test/run-make/c-static-rlib/Makefile +++ b/src/test/run-make/c-static-rlib/Makefile @@ -1,8 +1,8 @@ -include ../tools.mk -all: $(call STATICLIB,cfoo) +all: $(call NATIVE_STATICLIB,cfoo) $(RUSTC) foo.rs $(RUSTC) bar.rs $(call REMOVE_RLIBS,foo) - rm $(TMPDIR)/$(call STATICLIB_GLOB,cfoo) + rm $(call NATIVE_STATICLIB,cfoo) $(call RUN,bar) diff --git a/src/test/run-make/crate-name-priority/Makefile b/src/test/run-make/crate-name-priority/Makefile index 2fe5183243361..17ecb33ab28d0 100644 --- a/src/test/run-make/crate-name-priority/Makefile +++ b/src/test/run-make/crate-name-priority/Makefile @@ -7,5 +7,5 @@ all: rm $(TMPDIR)/$(call BIN,bar) $(RUSTC) foo1.rs rm $(TMPDIR)/$(call BIN,foo) - $(RUSTC) foo1.rs -o $(TMPDIR)/bar1 + $(RUSTC) foo1.rs -o $(TMPDIR)/$(call BIN,bar1) rm $(TMPDIR)/$(call BIN,bar1) diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index a7c6f5225a652..6fc12d3a75078 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -228,7 +228,7 @@ fn compile_program(input: &str, sysroot: PathBuf) let ast_map = driver::make_map(&sess, &mut hir_forest); driver::phase_3_run_analysis_passes( - sess, ast_map, &krate, &arenas, id, MakeGlobMap::No, |tcx, analysis| { + sess, ast_map, &arenas, id, MakeGlobMap::No, |tcx, analysis| { let trans = driver::phase_4_translate_to_llvm(tcx, analysis); diff --git a/src/test/run-make/extern-fn-generic/Makefile b/src/test/run-make/extern-fn-generic/Makefile index a325acbf687b5..cf897dba1f279 100644 --- a/src/test/run-make/extern-fn-generic/Makefile +++ b/src/test/run-make/extern-fn-generic/Makefile @@ -1,8 +1,6 @@ -include ../tools.mk -all: - $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o - $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o - $(RUSTC) testcrate.rs -L $(TMPDIR) - $(RUSTC) test.rs -L $(TMPDIR) +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) testcrate.rs + $(RUSTC) test.rs $(call RUN,test) || exit 1 diff --git a/src/test/run-make/extern-fn-mangle/Makefile b/src/test/run-make/extern-fn-mangle/Makefile index ea6971853fe99..042048ec25f63 100644 --- a/src/test/run-make/extern-fn-mangle/Makefile +++ b/src/test/run-make/extern-fn-mangle/Makefile @@ -1,7 +1,5 @@ -include ../tools.mk -all: - $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o - $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o - $(RUSTC) test.rs -L $(TMPDIR) +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) test.rs $(call RUN,test) || exit 1 diff --git a/src/test/run-make/extern-fn-with-packed-struct/Makefile b/src/test/run-make/extern-fn-with-packed-struct/Makefile index ea6971853fe99..042048ec25f63 100644 --- a/src/test/run-make/extern-fn-with-packed-struct/Makefile +++ b/src/test/run-make/extern-fn-with-packed-struct/Makefile @@ -1,7 +1,5 @@ -include ../tools.mk -all: - $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o - $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o - $(RUSTC) test.rs -L $(TMPDIR) +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) test.rs $(call RUN,test) || exit 1 diff --git a/src/test/run-make/extern-fn-with-packed-struct/test.c b/src/test/run-make/extern-fn-with-packed-struct/test.c index 121e48e84e46f..506954fca4617 100644 --- a/src/test/run-make/extern-fn-with-packed-struct/test.c +++ b/src/test/run-make/extern-fn-with-packed-struct/test.c @@ -1,11 +1,21 @@ // ignore-license // Pragma needed cause of gcc bug on windows: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 + +#ifdef _MSC_VER +#pragma pack(push,1) +struct Foo { + char a; + short b; + char c; +}; +#else #pragma pack(1) struct __attribute__((packed)) Foo { char a; short b; char c; }; +#endif struct Foo foo(struct Foo foo) { return foo; diff --git a/src/test/run-make/extern-fn-with-union/Makefile b/src/test/run-make/extern-fn-with-union/Makefile index a325acbf687b5..cf897dba1f279 100644 --- a/src/test/run-make/extern-fn-with-union/Makefile +++ b/src/test/run-make/extern-fn-with-union/Makefile @@ -1,8 +1,6 @@ -include ../tools.mk -all: - $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o - $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o - $(RUSTC) testcrate.rs -L $(TMPDIR) - $(RUSTC) test.rs -L $(TMPDIR) +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) testcrate.rs + $(RUSTC) test.rs $(call RUN,test) || exit 1 diff --git a/src/test/run-make/interdependent-c-libraries/Makefile b/src/test/run-make/interdependent-c-libraries/Makefile index cf7683479f08e..1268022e37b74 100644 --- a/src/test/run-make/interdependent-c-libraries/Makefile +++ b/src/test/run-make/interdependent-c-libraries/Makefile @@ -8,7 +8,7 @@ # correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo' # library will be stripped out, and the linkage will fail. -all: $(call STATICLIB,foo) $(call STATICLIB,bar) +all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar) $(RUSTC) foo.rs $(RUSTC) bar.rs $(RUSTC) main.rs -Z print-link-args diff --git a/src/test/run-make/issue-12446/Makefile b/src/test/run-make/issue-12446/Makefile index e864ee0058c7e..c412b0479fb84 100644 --- a/src/test/run-make/issue-12446/Makefile +++ b/src/test/run-make/issue-12446/Makefile @@ -1,6 +1,6 @@ -include ../tools.mk -all: $(call STATICLIB,foo) +all: $(call NATIVE_STATICLIB,foo) $(RUSTC) foo.rs $(RUSTC) bar.rs $(call RUN,bar) diff --git a/src/test/run-make/issue-14500/Makefile b/src/test/run-make/issue-14500/Makefile index 6ea3cf48ffbbd..bd94db0952028 100644 --- a/src/test/run-make/issue-14500/Makefile +++ b/src/test/run-make/issue-14500/Makefile @@ -13,5 +13,5 @@ endif all: $(RUSTC) foo.rs --crate-type=rlib $(RUSTC) bar.rs --crate-type=staticlib -C lto -L. -o $(TMPDIR)/libbar.a - $(CC) foo.c -lbar -o $(call RUN_BINFILE,foo) $(EXTRACFLAGS) + $(CC) foo.c $(TMPDIR)/libbar.a $(EXTRACFLAGS) $(call OUT_EXE,foo) $(call RUN,foo) diff --git a/src/test/run-make/issue-14698/Makefile b/src/test/run-make/issue-14698/Makefile new file mode 100644 index 0000000000000..28502f67e0747 --- /dev/null +++ b/src/test/run-make/issue-14698/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + TMP=fake TMPDIR=fake $(RUSTC) foo.rs 2>&1 | grep "couldn't create a temp dir:" diff --git a/src/test/parse-fail/struct-no-fields.rs b/src/test/run-make/issue-14698/foo.rs similarity index 68% rename from src/test/parse-fail/struct-no-fields.rs rename to src/test/run-make/issue-14698/foo.rs index fa5065b763027..7dc79f2043ba8 100644 --- a/src/test/parse-fail/struct-no-fields.rs +++ b/src/test/run-make/issue-14698/foo.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,9 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only - -struct Foo {} -//~^ ERROR: unit-like struct definition should be written as `struct Foo;` - fn main() {} diff --git a/src/test/run-make/issue-15460/Makefile b/src/test/run-make/issue-15460/Makefile index bc5e9b728694f..846805686a12a 100644 --- a/src/test/run-make/issue-15460/Makefile +++ b/src/test/run-make/issue-15460/Makefile @@ -1,6 +1,6 @@ -include ../tools.mk -all: $(TMPDIR)/libfoo.a +all: $(call NATIVE_STATICLIB,foo) $(RUSTC) foo.rs -C extra-filename=-383hf8 -C prefer-dynamic $(RUSTC) bar.rs $(call RUN,bar) diff --git a/src/test/run-make/issue-15460/foo.c b/src/test/run-make/issue-15460/foo.c index 2895ad473bf96..fdf595b574e33 100644 --- a/src/test/run-make/issue-15460/foo.c +++ b/src/test/run-make/issue-15460/foo.c @@ -1,2 +1,6 @@ // ignore-license + +#ifdef _WIN32 +__declspec(dllexport) +#endif void foo() {} diff --git a/src/test/run-make/issue-15460/foo.rs b/src/test/run-make/issue-15460/foo.rs index 6917fa5557980..8b96fe3682471 100644 --- a/src/test/run-make/issue-15460/foo.rs +++ b/src/test/run-make/issue-15460/foo.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(linked_from)] #![crate_type = "dylib"] #[link(name = "foo", kind = "static")] +#[linked_from = "foo"] extern { pub fn foo(); } diff --git a/src/test/run-make/issue-25581/Makefile b/src/test/run-make/issue-25581/Makefile index ea6971853fe99..042048ec25f63 100644 --- a/src/test/run-make/issue-25581/Makefile +++ b/src/test/run-make/issue-25581/Makefile @@ -1,7 +1,5 @@ -include ../tools.mk -all: - $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o - $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o - $(RUSTC) test.rs -L $(TMPDIR) +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) test.rs $(call RUN,test) || exit 1 diff --git a/src/test/run-make/issue-26092/Makefile b/src/test/run-make/issue-26092/Makefile index 1e66e3a53804f..0d94c99a3948a 100644 --- a/src/test/run-make/issue-26092/Makefile +++ b/src/test/run-make/issue-26092/Makefile @@ -2,4 +2,4 @@ all: $(RUSTC) -o "" blank.rs 2>&1 | \ - grep 'No such file or directory' + grep -i 'No such file or directory' diff --git a/src/test/run-make/link-path-order/Makefile b/src/test/run-make/link-path-order/Makefile index 116c7ae991cf6..eeea0e3714e7f 100644 --- a/src/test/run-make/link-path-order/Makefile +++ b/src/test/run-make/link-path-order/Makefile @@ -6,10 +6,12 @@ CORRECT_DIR=$(TMPDIR)/correct WRONG_DIR=$(TMPDIR)/wrong -all: $(TMPDIR)/libcorrect.a $(TMPDIR)/libwrong.a +F := $(call NATIVE_STATICLIB_FILE,foo) + +all: $(call NATIVE_STATICLIB,correct) $(call NATIVE_STATICLIB,wrong) mkdir -p $(CORRECT_DIR) $(WRONG_DIR) - mv $(TMPDIR)/libcorrect.a $(CORRECT_DIR)/libfoo.a - mv $(TMPDIR)/libwrong.a $(WRONG_DIR)/libfoo.a + mv $(call NATIVE_STATICLIB,correct) $(CORRECT_DIR)/$(F) + mv $(call NATIVE_STATICLIB,wrong) $(WRONG_DIR)/$(F) $(RUSTC) main.rs -o $(TMPDIR)/should_succeed -L $(CORRECT_DIR) -L $(WRONG_DIR) $(call RUN,should_succeed) $(RUSTC) main.rs -o $(TMPDIR)/should_fail -L $(WRONG_DIR) -L $(CORRECT_DIR) diff --git a/src/test/run-make/linkage-attr-on-static/Makefile b/src/test/run-make/linkage-attr-on-static/Makefile index 1871a5bbdc7f6..4befbe1446542 100644 --- a/src/test/run-make/linkage-attr-on-static/Makefile +++ b/src/test/run-make/linkage-attr-on-static/Makefile @@ -1,7 +1,5 @@ -include ../tools.mk -all: - $(CC) foo.c -c -o $(TMPDIR)/foo.o - $(AR) rcs $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o - $(RUSTC) bar.rs -lfoo -L $(TMPDIR) +all: $(call NATIVE_STATICLIB,foo) + $(RUSTC) bar.rs $(call RUN,bar) || exit 1 diff --git a/src/test/run-make/linkage-attr-on-static/bar.rs b/src/test/run-make/linkage-attr-on-static/bar.rs index 6125421bdeb6c..274401c448bad 100644 --- a/src/test/run-make/linkage-attr-on-static/bar.rs +++ b/src/test/run-make/linkage-attr-on-static/bar.rs @@ -14,6 +14,7 @@ #[linkage = "external"] static BAZ: i32 = 21; +#[link(name = "foo", kind = "static")] extern { fn what() -> i32; } diff --git a/src/test/run-make/lto-smoke-c/Makefile b/src/test/run-make/lto-smoke-c/Makefile index 6165afbeb222f..72c161abe9113 100644 --- a/src/test/run-make/lto-smoke-c/Makefile +++ b/src/test/run-make/lto-smoke-c/Makefile @@ -5,5 +5,7 @@ CC := $(CC:-g=) all: $(RUSTC) foo.rs -C lto - $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRACFLAGS) $(EXTRACXXFLAGS) + $(CC) bar.c $(TMPDIR)/libfoo.a \ + $(call OUT_EXE,bar) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) $(call RUN,bar) diff --git a/src/test/run-make/no-duplicate-libs/Makefile b/src/test/run-make/no-duplicate-libs/Makefile index fdb6048dc4d52..3f6a28c251a2f 100644 --- a/src/test/run-make/no-duplicate-libs/Makefile +++ b/src/test/run-make/no-duplicate-libs/Makefile @@ -1,7 +1,12 @@ -include ../tools.mk +ifdef IS_MSVC +# FIXME(#27979) +all: +else all: $(RUSTC) foo.rs $(RUSTC) bar.rs $(RUSTC) main.rs $(call RUN,main) +endif diff --git a/src/test/run-make/no-duplicate-libs/bar.c b/src/test/run-make/no-duplicate-libs/bar.c deleted file mode 100644 index a7b02a2f10b63..0000000000000 --- a/src/test/run-make/no-duplicate-libs/bar.c +++ /dev/null @@ -1,4 +0,0 @@ -// ignore-license -extern void foo(); - -void bar() { foo(); } diff --git a/src/test/run-make/no-duplicate-libs/foo.c b/src/test/run-make/no-duplicate-libs/foo.c deleted file mode 100644 index 2895ad473bf96..0000000000000 --- a/src/test/run-make/no-duplicate-libs/foo.c +++ /dev/null @@ -1,2 +0,0 @@ -// ignore-license -void foo() {} diff --git a/src/test/run-make/output-type-permutations/Makefile b/src/test/run-make/output-type-permutations/Makefile index 4efbd9ee48df2..e3c36b9c0b701 100644 --- a/src/test/run-make/output-type-permutations/Makefile +++ b/src/test/run-make/output-type-permutations/Makefile @@ -4,7 +4,8 @@ all: $(RUSTC) foo.rs --crate-type=rlib,dylib,staticlib $(call REMOVE_RLIBS,bar) $(call REMOVE_DYLIBS,bar) - rm $(TMPDIR)/$(call STATICLIB_GLOB,bar) + rm $(TMPDIR)/libbar.a + rm -f $(TMPDIR)/bar.{exp,lib} # Check that $(TMPDIR) is empty. [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] @@ -36,7 +37,7 @@ all: rm $(TMPDIR)/foo [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - $(RUSTC) foo.rs --emit=link -o $(TMPDIR)/foo + $(RUSTC) foo.rs --emit=link -o $(TMPDIR)/$(call BIN,foo) rm $(TMPDIR)/$(call BIN,foo) [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] @@ -44,15 +45,16 @@ all: rm $(TMPDIR)/foo [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - $(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/foo - rm $(TMPDIR)/$(call BIN,foo) # FIXME 13794 + $(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/$(call BIN,foo) + rm $(TMPDIR)/$(call BIN,foo) + rm -f $(TMPDIR)/foo.{exp,lib} [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] $(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo rm $(TMPDIR)/foo [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] - $(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/foo + $(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/$(call BIN,foo) rm $(TMPDIR)/$(call BIN,foo) [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] @@ -60,7 +62,7 @@ all: rm $(TMPDIR)/bar.ll rm $(TMPDIR)/bar.s rm $(TMPDIR)/bar.o - rm $(TMPDIR)/$(call STATICLIB_GLOB,bar) + rm $(TMPDIR)/libbar.a mv $(TMPDIR)/bar.bc $(TMPDIR)/foo.bc # Don't check that the $(TMPDIR) is empty - we left `foo.bc` for later # comparison. diff --git a/src/test/run-make/relocation-model/Makefile b/src/test/run-make/relocation-model/Makefile index 2fcdd32bfcbd4..b22f34fa35b54 100644 --- a/src/test/run-make/relocation-model/Makefile +++ b/src/test/run-make/relocation-model/Makefile @@ -1,15 +1,21 @@ -include ../tools.mk -all: +all: others $(RUSTC) -C relocation-model=dynamic-no-pic foo.rs $(call RUN,foo) $(RUSTC) -C relocation-model=default foo.rs $(call RUN,foo) + $(RUSTC) -C relocation-model=default --crate-type=dylib foo.rs + $(RUSTC) -C relocation-model=dynamic-no-pic --crate-type=dylib foo.rs + +ifdef IS_MSVC +# FIXME(#28026) +others: +else +others: $(RUSTC) -C relocation-model=static foo.rs $(call RUN,foo) - - $(RUSTC) -C relocation-model=default --crate-type=dylib foo.rs $(RUSTC) -C relocation-model=static --crate-type=dylib foo.rs - $(RUSTC) -C relocation-model=dynamic-no-pic --crate-type=dylib foo.rs +endif diff --git a/src/test/run-make/static-dylib-by-default/Makefile b/src/test/run-make/static-dylib-by-default/Makefile index 1505e679af011..8bd05dc201fcf 100644 --- a/src/test/run-make/static-dylib-by-default/Makefile +++ b/src/test/run-make/static-dylib-by-default/Makefile @@ -1,9 +1,16 @@ -include ../tools.mk +TO_LINK := $(call DYLIB,bar) +ifdef IS_MSVC +LINK_ARG = $(TO_LINK:dll=lib) +else +LINK_ARG = $(TO_LINK) +endif + all: $(RUSTC) foo.rs $(RUSTC) bar.rs - $(CC) main.c -o $(call RUN_BINFILE,main) -lbar $(EXTRACFLAGS) + $(CC) main.c $(call OUT_EXE,main) $(LINK_ARG) $(EXTRACFLAGS) rm $(TMPDIR)/*.rlib rm $(call DYLIB,foo) $(call RUN,main) diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index 223296286bd89..14d8e468f50d3 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -7,7 +7,7 @@ TARGET_RPATH_ENV = \ BARE_RUSTC := $(HOST_RPATH_ENV) $(RUSTC) RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) -CC := $(CC) -L $(TMPDIR) +#CC := $(CC) -L $(TMPDIR) HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py # This is the name of the binary we will generate and run; use this @@ -19,8 +19,6 @@ RUN_BINFILE = $(TMPDIR)/$(1) # variable before running the binary. RLIB_GLOB = lib$(1)*.rlib -STATICLIB = $(TMPDIR)/lib$(1).a -STATICLIB_GLOB = lib$(1)*.a BIN = $(1) UNAME = $(shell uname) @@ -33,27 +31,48 @@ RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE) FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0 DYLIB_GLOB = lib$(1)*.dylib DYLIB = $(TMPDIR)/lib$(1).dylib -RPATH_LINK_SEARCH = +STATICLIB = $(TMPDIR)/lib$(1).a +STATICLIB_GLOB = lib$(1)*.a else ifdef IS_WINDOWS RUN = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE) FAIL = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE) && exit 1 || exit 0 DYLIB_GLOB = $(1)*.dll DYLIB = $(TMPDIR)/$(1).dll +STATICLIB = $(TMPDIR)/$(1).lib +STATICLIB_GLOB = $(1)*.lib BIN = $(1).exe -RPATH_LINK_SEARCH = else RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE) FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0 DYLIB_GLOB = lib$(1)*.so DYLIB = $(TMPDIR)/lib$(1).so -RPATH_LINK_SEARCH = -Wl,-rpath-link=$(1) +STATICLIB = $(TMPDIR)/lib$(1).a +STATICLIB_GLOB = lib$(1)*.a +endif endif + +ifdef IS_MSVC +COMPILE_OBJ = $(CC) -c -Fo:`cygpath -w $(1)` $(2) +NATIVE_STATICLIB_FILE = $(1).lib +NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1)) +OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \ + -Fo:`cygpath -w $(TMPDIR)/$(1).obj` +else +COMPILE_OBJ = $(CC) -c -o $(1) $(2) +NATIVE_STATICLIB_FILE = lib$(1).a +NATIVE_STATICLIB = $(call STATICLIB,$(1)) +OUT_EXE=-o $(TMPDIR)/$(1) endif + # Extra flags needed to compile a working executable with the standard library ifdef IS_WINDOWS +ifdef IS_MSVC + EXTRACFLAGS := ws2_32.lib userenv.lib shell32.lib advapi32.lib +else EXTRACFLAGS := -lws2_32 -luserenv +endif else ifeq ($(UNAME),Darwin) else @@ -80,12 +99,20 @@ REMOVE_RLIBS = rm $(TMPDIR)/$(call RLIB_GLOB,$(1)) %.a: %.o ar crus $@ $< +%.lib: lib%.o + ar crus $@ $< %.dylib: %.o $(CC) -dynamiclib -Wl,-dylib -o $@ $< %.so: %.o $(CC) -o $@ $< -shared + +ifdef IS_MSVC +%.dll: lib%.o + $(CC) $< -link -dll -out:`cygpath -w $@` +else %.dll: lib%.o $(CC) -o $@ $< -shared +endif $(TMPDIR)/lib%.o: %.c - $(CC) -c -o $@ $< + $(call COMPILE_OBJ,$@,$<) diff --git a/src/test/run-pass/empty-struct-with-braces.rs b/src/test/run-pass/empty-struct-with-braces.rs new file mode 100644 index 0000000000000..dc806acb980dd --- /dev/null +++ b/src/test/run-pass/empty-struct-with-braces.rs @@ -0,0 +1,56 @@ +// 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. + +// Empty struct defined with braces add names into type namespace +// Empty struct defined without braces add names into both type and value namespaces + +#![feature(braced_empty_structs)] + +struct Empty1 {} +struct Empty2; +struct Empty3 {} +const Empty3: Empty3 = Empty3 {}; + +fn main() { + let e1: Empty1 = Empty1 {}; + let e2: Empty2 = Empty2 {}; + let e2: Empty2 = Empty2; + let e3: Empty3 = Empty3 {}; + let e3: Empty3 = Empty3; + + match e1 { + Empty1 {} => () + } + match e2 { + Empty2 {} => () + } + match e2 { + Empty2 => () + } + match e3 { + Empty3 {} => () + } + match e3 { + Empty3 => () + } + match e1 { + Empty1 { .. } => () + } + match e2 { + Empty2 { .. } => () + } + match e3 { + Empty3 { .. } => () + } + + let e11 = Empty1 { ..e1 }; + let e22 = Empty2 { ..e2 }; + let e33 = Empty3 { ..e3 }; +} diff --git a/src/test/compile-fail/issue-3993-2.rs b/src/test/run-pass/issue-16819.rs similarity index 65% rename from src/test/compile-fail/issue-3993-2.rs rename to src/test/run-pass/issue-16819.rs index 9d9e91a141be3..a9abb99696f59 100644 --- a/src/test/compile-fail/issue-3993-2.rs +++ b/src/test/run-pass/issue-16819.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,16 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use zoo::bird::{duck, goose}; +//`#[cfg]` on struct field permits empty unusable struct -mod zoo { - pub enum bird { - pub duck, //~ ERROR: unnecessary `pub` visibility - goose - } -} +#![feature(braced_empty_structs)] +struct S { + #[cfg(untrue)] + a: int, +} fn main() { - let y = goose; + let s = S {}; } diff --git a/src/test/run-pass/issue-24533.rs b/src/test/run-pass/issue-24533.rs new file mode 100644 index 0000000000000..440a4184780cd --- /dev/null +++ b/src/test/run-pass/issue-24533.rs @@ -0,0 +1,32 @@ +// 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. + +use std::slice::Iter; +use std::io::{Error, ErrorKind, Result}; +use std::vec::*; + +fn foo(it: &mut Iter) -> Result { + Ok(*it.next().unwrap()) +} + +fn bar() -> Result { + let data: Vec = Vec::new(); + + if true { + return Err(Error::new(ErrorKind::NotFound, "msg")); + } + + let mut it = data.iter(); + foo(&mut it) +} + +fn main() { + bar(); +} diff --git a/src/test/run-pass/issue-26905.rs b/src/test/run-pass/issue-26905.rs new file mode 100644 index 0000000000000..0ad193bb28c99 --- /dev/null +++ b/src/test/run-pass/issue-26905.rs @@ -0,0 +1,31 @@ +// 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. + +#![feature(unsize, coerce_unsized)] + +// Verfies that PhantomData is ignored for DST coercions + +use std::marker::{Unsize, PhantomData}; +use std::ops::CoerceUnsized; + +struct MyRc { + _ptr: *const T, + _boo: PhantomData, +} + +impl, U: ?Sized> CoerceUnsized> for MyRc{ } + +fn main() { + let data = [1, 2, 3]; + let iter = data.iter(); + let x = MyRc { _ptr: &iter, _boo: PhantomData }; + let _y: MyRc> = x; +} + diff --git a/src/test/run-pass/unary-minus-suffix-inference.rs b/src/test/run-pass/unary-minus-suffix-inference.rs index 9d685e0263f22..fdb70fe248eff 100644 --- a/src/test/run-pass/unary-minus-suffix-inference.rs +++ b/src/test/run-pass/unary-minus-suffix-inference.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(negate_unsigned)] + pub fn main() { let a = 1; let a_neg: i8 = -a; diff --git a/src/test/run-pass/x86stdcall2.rs b/src/test/run-pass/x86stdcall2.rs index c9742b0645e1d..f3bf5d9c6843f 100644 --- a/src/test/run-pass/x86stdcall2.rs +++ b/src/test/run-pass/x86stdcall2.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -pub type HANDLE = u32; +pub type HANDLE = usize; pub type DWORD = u32; pub type SIZE_T = u32; pub type LPVOID = usize;