From 5c5cca58f7c8e59703892d9500327aafdd44e45e Mon Sep 17 00:00:00 2001 From: Jack Wilson Date: Sun, 6 Sep 2015 16:23:44 -0700 Subject: [PATCH 01/61] Small syntax and formatting changes --- src/doc/trpl/guessing-game.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index 4a35022b03c91..3a4328562f872 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -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 From 7f5ec6c392c53225d85b160bcef3cedbc366ed72 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Mon, 14 Sep 2015 13:52:32 +0200 Subject: [PATCH 02/61] Disable browser history API on file:/ URLs history.pushState is defined, but not working whenever document.origin is "null" (literally that string, not just the null object). This is due to some security considerations and is unlikely to be ever working. For now just disable the usage of the history API when the documentation is accessed through a file:/ URL. See https://code.google.com/p/chromium/issues/detail?id=301210 for a Chrome-specific issue on the history API on file:/ URLs Closes #25953 --- src/librustdoc/html/static/main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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) { From b096403d432afedc5d9ab1f26e3c1504f5015fe2 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 12 Sep 2015 19:19:32 -0600 Subject: [PATCH 03/61] Ignore PhantomData when checking CoerceUnsized implementations --- src/librustc/middle/ty/sty.rs | 8 +++++++ src/librustc_trans/trans/expr.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 9 +++++++- src/test/compile-fail/issue-26905.rs | 34 ++++++++++++++++++++++++++++ src/test/run-pass/issue-26905.rs | 31 +++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/issue-26905.rs create mode 100644 src/test/run-pass/issue-26905.rs diff --git a/src/librustc/middle/ty/sty.rs b/src/librustc/middle/ty/sty.rs index 3969738a22e86..0227122b569d6 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_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 7d8996867c016..ea2b5c1f290cc 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -533,7 +533,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); } } 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/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/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; +} + From 320880eed5e960f6107cfbe039a5eba33f209f32 Mon Sep 17 00:00:00 2001 From: christopherdumas Date: Tue, 15 Sep 2015 07:54:43 -0700 Subject: [PATCH 04/61] Fix option link and anchor links. --- src/doc/trpl/error-handling.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 673dc950ecce4..2b590c82a89bf 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -33,12 +33,12 @@ systems may want to jump around. * [Composing `Option` and `Result`](#composing-option-and-result) * [The limits of combinators](#the-limits-of-combinators) * [Early returns](#early-returns) - * [The `try!` macro](#the-try-macro) + * [The `try!` macro](#the-try!-macro) * [Defining your own error type](#defining-your-own-error-type) * [Standard library traits used for error handling](#standard-library-traits-used-for-error-handling) * [The `Error` trait](#the-error-trait) * [The `From` trait](#the-from-trait) - * [The real `try!` macro](#the-real-try-macro) + * [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) @@ -120,10 +120,9 @@ 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][1]: +The `Option` type is [defined in the standard library][5]: ```rust enum Option { From b69a51164d078b00d97a4aa7d4a91ec3f4f5a074 Mon Sep 17 00:00:00 2001 From: christopherdumas Date: Tue, 15 Sep 2015 10:31:48 -0700 Subject: [PATCH 05/61] Added anchors for the code snippets. --- src/doc/trpl/error-handling.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 2b590c82a89bf..0687c2b13b5b5 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -87,7 +87,9 @@ 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; fn main() { @@ -137,6 +139,7 @@ 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. From 1b3745fe145a18df44156f24c5c31ca9bf26883d Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 9 Sep 2015 12:12:25 +0100 Subject: [PATCH 06/61] Add a comment that the `Atomic*` are all implicitly `Send` --- src/libcore/sync/atomic.rs | 3 +++ 1 file changed, 3 insertions(+) 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. From 804f024edab8b85f276a9a3fbfa23215a4688328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Wed, 16 Sep 2015 10:17:38 +0200 Subject: [PATCH 07/61] Simplify sample code for {Option, Result}::iter_mut Fixes #28431 --- src/libcore/option.rs | 2 +- src/libcore/result.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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)); From 1614173b589620ba33aa91c49ea82513067566fb Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Tue, 15 Sep 2015 15:11:07 +0200 Subject: [PATCH 08/61] Specialize `PartialOrd` for totally ordered primitive types Knowing the result of equality comparison can enable additional optimizations in LLVM. Additionally, this makes it obvious that `partial_cmp` on totally ordered types cannot return `None`. --- src/libcore/cmp.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index aea5feb4be1ff..dc550fc2173af 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -463,17 +463,35 @@ 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 { + if *self == *other { Some(Equal) } + else if *self < *other { Some(Less) } + else { Some(Greater) } + } + #[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 } } } )*) From d04b8b5818819470457fc00f87176b273d756980 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Tue, 15 Sep 2015 23:20:18 +0200 Subject: [PATCH 09/61] Improve PartialOrd for slices Reusing the same idea as in #26884, we can exploit the fact that the length of slices is known, hence we can use a counted loop instead of iterators, which means that we only need a single counter, instead of having to increment and check one pointer for each iterator. Using the generic implementation of the boolean comparison operators (`lt`, `le`, `gt`, `ge`) provides further speedup for simple types. This happens because the loop scans elements checking for equality and dispatches to element comparison or length comparison depending on the result of the prefix comparison. ``` test u8_cmp ... bench: 14,043 ns/iter (+/- 1,732) test u8_lt ... bench: 16,156 ns/iter (+/- 1,864) test u8_partial_cmp ... bench: 16,250 ns/iter (+/- 2,608) test u16_cmp ... bench: 15,764 ns/iter (+/- 1,420) test u16_lt ... bench: 19,833 ns/iter (+/- 2,826) test u16_partial_cmp ... bench: 19,811 ns/iter (+/- 2,240) test u32_cmp ... bench: 15,792 ns/iter (+/- 3,409) test u32_lt ... bench: 18,577 ns/iter (+/- 2,075) test u32_partial_cmp ... bench: 18,603 ns/iter (+/- 5,666) test u64_cmp ... bench: 16,337 ns/iter (+/- 2,511) test u64_lt ... bench: 18,074 ns/iter (+/- 7,914) test u64_partial_cmp ... bench: 17,909 ns/iter (+/- 1,105) ``` ``` test u8_cmp ... bench: 6,511 ns/iter (+/- 982) test u8_lt ... bench: 6,671 ns/iter (+/- 919) test u8_partial_cmp ... bench: 7,118 ns/iter (+/- 1,623) test u16_cmp ... bench: 6,689 ns/iter (+/- 921) test u16_lt ... bench: 6,712 ns/iter (+/- 947) test u16_partial_cmp ... bench: 6,725 ns/iter (+/- 780) test u32_cmp ... bench: 7,704 ns/iter (+/- 1,294) test u32_lt ... bench: 7,611 ns/iter (+/- 3,062) test u32_partial_cmp ... bench: 7,640 ns/iter (+/- 1,149) test u64_cmp ... bench: 7,517 ns/iter (+/- 2,164) test u64_lt ... bench: 7,579 ns/iter (+/- 1,048) test u64_partial_cmp ... bench: 7,629 ns/iter (+/- 1,195) ``` --- src/libcore/slice.rs | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 8d3d798afef13..7af808d1e8283 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1558,8 +1558,18 @@ impl Eq for [T] {} #[stable(feature = "rust1", since = "1.0.0")] impl Ord for [T] { + #[inline] fn cmp(&self, other: &[T]) -> Ordering { - self.iter().cmp(other.iter()) + let l = cmp::min(self.len(), other.len()); + + for i in 0..l { + match self[i].cmp(&other[i]) { + Ordering::Equal => (), + non_eq => return non_eq, + } + } + + self.len().cmp(&other.len()) } } @@ -1567,22 +1577,15 @@ impl Ord for [T] { 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()); + + for i in 0..l { + match self[i].partial_cmp(&other[i]) { + Some(Ordering::Equal) => (), + non_eq => return non_eq, + } + } + + self.len().partial_cmp(&other.len()) } } From 9a626df476119b79f8ebfa7d92f4a82ac9ef893e Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Wed, 16 Sep 2015 06:50:24 -0400 Subject: [PATCH 10/61] Add test for #24533 Closes #24533. --- src/test/run-pass/issue-24533.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/run-pass/issue-24533.rs 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(); +} From bf9254a75e06f61ecd837e2f90ed0afc22ffdede Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Wed, 16 Sep 2015 15:25:51 +0200 Subject: [PATCH 11/61] Reuse cmp in totally ordered types Instead of manually defining it, `partial_cmp` can simply wrap the result of `cmp` for totally ordered types. --- src/libcore/cmp.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index dc550fc2173af..3344d7ea5d7fc 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -471,9 +471,7 @@ mod impls { impl PartialOrd for $t { #[inline] fn partial_cmp(&self, other: &$t) -> Option { - if *self == *other { Some(Equal) } - else if *self < *other { Some(Less) } - else { Some(Greater) } + Some(self.cmp(other)) } #[inline] fn lt(&self, other: &$t) -> bool { (*self) < (*other) } From 369a9dc302582145e37cf335c454fb6bd74906c6 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Wed, 16 Sep 2015 15:27:14 +0200 Subject: [PATCH 12/61] Remove boundary checks in slice comparison operators In order to get rid of all range checks, the compiler needs to explicitly see that the slices it iterates over are as long as the loop variable upper bound. This further improves the performance of slice comparison: ``` test u8_cmp ... bench: 4,761 ns/iter (+/- 1,203) test u8_lt ... bench: 4,579 ns/iter (+/- 649) test u8_partial_cmp ... bench: 4,768 ns/iter (+/- 761) test u16_cmp ... bench: 4,607 ns/iter (+/- 580) test u16_lt ... bench: 4,681 ns/iter (+/- 567) test u16_partial_cmp ... bench: 4,607 ns/iter (+/- 967) test u32_cmp ... bench: 4,448 ns/iter (+/- 891) test u32_lt ... bench: 4,546 ns/iter (+/- 992) test u32_partial_cmp ... bench: 4,415 ns/iter (+/- 646) test u64_cmp ... bench: 4,380 ns/iter (+/- 1,184) test u64_lt ... bench: 5,684 ns/iter (+/- 602) test u64_partial_cmp ... bench: 4,663 ns/iter (+/- 1,158) ``` --- src/libcore/slice.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 7af808d1e8283..af8db18a8737c 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1561,9 +1561,11 @@ impl Ord for [T] { #[inline] fn cmp(&self, other: &[T]) -> Ordering { let l = cmp::min(self.len(), other.len()); + let lhs = &self[..l]; + let rhs = &other[..l]; for i in 0..l { - match self[i].cmp(&other[i]) { + match lhs[i].cmp(&rhs[i]) { Ordering::Equal => (), non_eq => return non_eq, } @@ -1578,9 +1580,11 @@ impl PartialOrd for [T] { #[inline] fn partial_cmp(&self, other: &[T]) -> Option { let l = cmp::min(self.len(), other.len()); + let lhs = &self[..l]; + let rhs = &other[..l]; for i in 0..l { - match self[i].partial_cmp(&other[i]) { + match lhs[i].partial_cmp(&rhs[i]) { Some(Ordering::Equal) => (), non_eq => return non_eq, } From 08b9edfe94c2680bde224b9dc6dd4a0de6616a07 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Wed, 16 Sep 2015 16:09:01 +0200 Subject: [PATCH 13/61] Remove inline attribute Be more conservative with inlining. --- src/libcore/slice.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index af8db18a8737c..dbebea37f6fc8 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1558,7 +1558,6 @@ impl Eq for [T] {} #[stable(feature = "rust1", since = "1.0.0")] impl Ord for [T] { - #[inline] fn cmp(&self, other: &[T]) -> Ordering { let l = cmp::min(self.len(), other.len()); let lhs = &self[..l]; @@ -1577,7 +1576,6 @@ impl Ord for [T] { #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for [T] { - #[inline] fn partial_cmp(&self, other: &[T]) -> Option { let l = cmp::min(self.len(), other.len()); let lhs = &self[..l]; From 74dc146f4296c209bf688d7cddff51eab48e8496 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Wed, 16 Sep 2015 16:09:23 +0200 Subject: [PATCH 14/61] Explain explicit slicing in slice cmp and partial_cmp methods The explicit slicing is needed in order to enable additional range check optimizations in the compiler. --- src/libcore/slice.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index dbebea37f6fc8..5518bacb019e8 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1560,6 +1560,9 @@ impl Eq for [T] {} impl Ord for [T] { fn cmp(&self, other: &[T]) -> Ordering { 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]; @@ -1578,6 +1581,9 @@ impl Ord for [T] { impl PartialOrd for [T] { fn partial_cmp(&self, other: &[T]) -> Option { 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]; From f5b69b3d9c6cac49e967f43dd5fb1b8aa7071080 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Wed, 16 Sep 2015 11:44:41 -0400 Subject: [PATCH 15/61] Remove incorrect test for #22872 The original issue was not fixed, but the test passed due to disabled debug assertions. --- src/test/compile-fail/issue-22872.rs | 36 ---------------------------- 1 file changed, 36 deletions(-) delete mode 100644 src/test/compile-fail/issue-22872.rs 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() {} From 7352722cdddf2869341b55a3479e3a1124d5be3c Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Wed, 16 Sep 2015 13:52:02 -0400 Subject: [PATCH 16/61] Emit an error upon failing to create a temp dir instead of panicking Closes #14698. --- src/librustc_trans/back/link.rs | 6 +++++- src/test/run-make/issue-14698/Makefile | 4 ++++ src/test/run-make/issue-14698/foo.rs | 11 +++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/test/run-make/issue-14698/Makefile create mode 100644 src/test/run-make/issue-14698/foo.rs diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index d5486e84fc431..fdce46ba272a2 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -543,7 +543,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/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/run-make/issue-14698/foo.rs b/src/test/run-make/issue-14698/foo.rs new file mode 100644 index 0000000000000..7dc79f2043ba8 --- /dev/null +++ b/src/test/run-make/issue-14698/foo.rs @@ -0,0 +1,11 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} From dfe88c09b86c47dad3e4758469beff409ae8533a Mon Sep 17 00:00:00 2001 From: Dongie Agnir Date: Wed, 16 Sep 2015 18:56:56 -0400 Subject: [PATCH 17/61] Change OSX version req wording to match Linux. --- src/doc/trpl/installing-rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 76856e19ff3c7c699931d0acee8e61bc0dfec512 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 10 Sep 2015 16:40:59 +1200 Subject: [PATCH 18/61] Add an early lint pass for lints that operate on the AST There is a minor [breaking-change] for lint authors - some functions which were previously defined on `lint::Context` have moved to a trait - `LintContext`, you may need to import that trait to avoid name resolution errors. --- src/librustc/lint/context.rs | 476 ++++++++++++++++++++++++++------ src/librustc/lint/mod.rs | 114 +++++--- src/librustc/plugin/registry.rs | 1 - src/librustc_driver/driver.rs | 8 +- src/librustc_driver/pretty.rs | 6 +- src/librustc_lint/builtin.rs | 169 ++++++------ src/librustdoc/core.rs | 1 - 7 files changed, 563 insertions(+), 212 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index dade1f4eb26fa..3f1a1ed48a147 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -36,15 +36,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. @@ -248,8 +248,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 +272,35 @@ pub struct Context<'a, 'tcx: 'a> { node_levels: RefCell>, } +pub type Context<'a, 'tcx: 'a> = LateContext<'a, 'tcx>; + +/// 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),*) => ({ // 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().passes.take().unwrap(); for obj in &mut passes { obj.$f($cx, $($args),*); } - $cx.lints.passes = Some(passes); + $cx.mut_lints().passes = Some(passes); }) } /// Parse the lint attributes into a vector, with `Err`s for malformed lint @@ -364,65 +384,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: &[hir::Attribute]); + fn exit_attrs(&mut self, attrs: &[hir::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 +438,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 +465,90 @@ 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); + } + } + + fn with_ast_lint_attrs(&mut self, + attrs: &[ast::Attribute], + f: F) + where F: FnOnce(&mut Self), + { + self.with_lint_attrs(&lower_attrs(attrs), f) + } +} + + +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. + 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 util::IdVisitor) + 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) { let mut v = util::IdVisitor { operation: self, @@ -499,41 +559,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: &[hir::Attribute]) { + run_lints!(self, enter_lint_attrs, attrs); + } + + fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { + run_lints!(self, exit_lint_attrs, 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: &[hir::Attribute]) { + run_lints!(self, ast_enter_lint_attrs, attrs); + } + + fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { + run_lints!(self, ast_exit_lint_attrs, 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); 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); + 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); + 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); + 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); + 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); + hir_visit::walk_fn(self, fk, decl, body, span); } fn visit_struct_def(&mut self, @@ -542,28 +656,28 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { g: &hir::Generics, id: ast::NodeId) { run_lints!(self, check_struct_def, s, ident, g, id); - visit::walk_struct_def(self, s); + hir_visit::walk_struct_def(self, s); run_lints!(self, check_struct_def_post, 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); + 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); + hir_visit::walk_variant(cx, v, g); run_lints!(cx, check_variant_post, v, g); }) } fn visit_ty(&mut self, t: &hir::Ty) { run_lints!(self, check_ty, t); - visit::walk_ty(self, t); + hir_visit::walk_ty(self, t); } fn visit_ident(&mut self, sp: Span, id: ast::Ident) { @@ -572,27 +686,27 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { 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); + 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); + 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); + 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); + 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); + hir_visit::walk_decl(self, d); } fn visit_expr_post(&mut self, e: &hir::Expr) { @@ -601,14 +715,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_generics(&mut self, g: &hir::Generics) { run_lints!(self, check_generics, g); - visit::walk_generics(self, 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); 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); }); } @@ -616,7 +730,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { self.with_lint_attrs(&impl_item.attrs, |cx| { run_lints!(cx, check_impl_item, 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); }); } @@ -634,12 +748,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_explicit_self(&mut self, es: &hir::ExplicitSelf) { run_lints!(self, check_explicit_self, es); - visit::walk_explicit_self(self, 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); + hir_visit::walk_path(self, p); } fn visit_attribute(&mut self, attr: &ast::Attribute) { @@ -647,10 +761,170 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } } +impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { + fn visit_item(&mut self, it: &ast::Item) { + self.with_ast_lint_attrs(&it.attrs, |cx| { + run_lints!(cx, check_ast_item, 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_ast_lint_attrs(&it.attrs, |cx| { + run_lints!(cx, check_ast_foreign_item, it); + ast_visit::walk_foreign_item(cx, it); + }) + } + + fn visit_pat(&mut self, p: &ast::Pat) { + run_lints!(self, check_ast_pat, p); + ast_visit::walk_pat(self, p); + } + + fn visit_expr(&mut self, e: &ast::Expr) { + run_lints!(self, check_ast_expr, e); + ast_visit::walk_expr(self, e); + } + + fn visit_stmt(&mut self, s: &ast::Stmt) { + run_lints!(self, check_ast_stmt, 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_ast_fn, 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_ast_struct_def, s, ident, g, id); + ast_visit::walk_struct_def(self, s); + run_lints!(self, check_ast_struct_def_post, s, ident, g, id); + } + + fn visit_struct_field(&mut self, s: &ast::StructField) { + self.with_ast_lint_attrs(&s.node.attrs, |cx| { + run_lints!(cx, check_ast_struct_field, s); + ast_visit::walk_struct_field(cx, s); + }) + } + + fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) { + self.with_ast_lint_attrs(&v.node.attrs, |cx| { + run_lints!(cx, check_ast_variant, v, g); + ast_visit::walk_variant(cx, v, g); + run_lints!(cx, check_ast_variant_post, v, g); + }) + } + + fn visit_ty(&mut self, t: &ast::Ty) { + run_lints!(self, check_ast_ty, t); + ast_visit::walk_ty(self, t); + } + + fn visit_ident(&mut self, sp: Span, id: ast::Ident) { + run_lints!(self, check_ast_ident, sp, id); + } + + fn visit_mod(&mut self, m: &ast::Mod, s: Span, n: ast::NodeId) { + run_lints!(self, check_ast_mod, m, s, n); + ast_visit::walk_mod(self, m); + } + + fn visit_local(&mut self, l: &ast::Local) { + run_lints!(self, check_ast_local, l); + ast_visit::walk_local(self, l); + } + + fn visit_block(&mut self, b: &ast::Block) { + run_lints!(self, check_ast_block, b); + ast_visit::walk_block(self, b); + } + + fn visit_arm(&mut self, a: &ast::Arm) { + run_lints!(self, check_ast_arm, a); + ast_visit::walk_arm(self, a); + } + + fn visit_decl(&mut self, d: &ast::Decl) { + run_lints!(self, check_ast_decl, d); + ast_visit::walk_decl(self, d); + } + + fn visit_expr_post(&mut self, e: &ast::Expr) { + run_lints!(self, check_ast_expr_post, e); + } + + fn visit_generics(&mut self, g: &ast::Generics) { + run_lints!(self, check_ast_generics, g); + ast_visit::walk_generics(self, g); + } + + fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { + self.with_ast_lint_attrs(&trait_item.attrs, |cx| { + run_lints!(cx, check_ast_trait_item, 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_ast_lint_attrs(&impl_item.attrs, |cx| { + run_lints!(cx, check_ast_impl_item, 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_ast_opt_lifetime_ref, sp, lt); + } + + fn visit_lifetime_ref(&mut self, lt: &ast::Lifetime) { + run_lints!(self, check_ast_lifetime_ref, lt); + } + + fn visit_lifetime_def(&mut self, lt: &ast::LifetimeDef) { + run_lints!(self, check_ast_lifetime_def, lt); + } + + fn visit_explicit_self(&mut self, es: &ast::ExplicitSelf) { + run_lints!(self, check_ast_explicit_self, es); + ast_visit::walk_explicit_self(self, es); + } + + fn visit_path(&mut self, p: &ast::Path, id: ast::NodeId) { + run_lints!(self, check_ast_path, p, id); + ast_visit::walk_path(self, p); + } + + fn visit_attribute(&mut self, attr: &ast::Attribute) { + run_lints!(self, check_ast_attribute, 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.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.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 { @@ -661,7 +935,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`. @@ -673,7 +947,7 @@ impl LintPass for GatherNodeLevels { lint_array!() } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + 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 +972,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); - 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 +1001,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_ast_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_ast_crate, 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..d30f8f3c53ad2 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, Context, LintContext, LintStore, + raw_emit_lint, check_crate, check_ast_crate, gather_attrs, GatherNodeLevels}; /// Specification of a single lint. @@ -126,46 +128,92 @@ pub trait LintPass { /// `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, + 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) { } + + fn check_ast_ident(&mut self, _: &EarlyContext, _: Span, _: ast::Ident) { } + fn check_ast_crate(&mut self, _: &EarlyContext, _: &ast::Crate) { } + fn check_ast_mod(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { } + fn check_ast_foreign_item(&mut self, _: &EarlyContext, _: &ast::ForeignItem) { } + fn check_ast_item(&mut self, _: &EarlyContext, _: &ast::Item) { } + fn check_ast_local(&mut self, _: &EarlyContext, _: &ast::Local) { } + fn check_ast_block(&mut self, _: &EarlyContext, _: &ast::Block) { } + fn check_ast_stmt(&mut self, _: &EarlyContext, _: &ast::Stmt) { } + fn check_ast_arm(&mut self, _: &EarlyContext, _: &ast::Arm) { } + fn check_ast_pat(&mut self, _: &EarlyContext, _: &ast::Pat) { } + fn check_ast_decl(&mut self, _: &EarlyContext, _: &ast::Decl) { } + fn check_ast_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { } + fn check_ast_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { } + fn check_ast_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { } + fn check_ast_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { } + fn check_ast_fn(&mut self, _: &EarlyContext, + _: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { } + fn check_ast_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { } + fn check_ast_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { } + fn check_ast_struct_def(&mut self, _: &EarlyContext, + _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } + fn check_ast_struct_def_post(&mut self, _: &EarlyContext, + _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } + fn check_ast_struct_field(&mut self, _: &EarlyContext, _: &ast::StructField) { } + fn check_ast_variant(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } + fn check_ast_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } + fn check_ast_opt_lifetime_ref(&mut self, + _: &EarlyContext, + _: Span, + _: &Option) { } + fn check_ast_lifetime_ref(&mut self, _: &EarlyContext, _: &ast::Lifetime) { } + fn check_ast_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { } + fn check_ast_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { } + fn check_ast_mac(&mut self, _: &EarlyContext, _: &ast::Mac) { } + fn check_ast_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { } + fn check_ast_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, _: &LateContext, _: &[ast::Attribute]) { } /// Counterpart to `enter_lint_attrs`. - fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { } + fn exit_lint_attrs(&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 ast_enter_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } + + /// Counterpart to `ast_enter_lint_attrs`. + fn ast_exit_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } } /// A lint pass boxed up as a trait object. diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index e79721b4347a6..ca7ce2308a1cb 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -89,7 +89,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) => { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f3038624ac107..4ec13ba35993d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -132,7 +132,6 @@ pub fn compile_input(sess: Session, phase_3_run_analysis_passes(sess, ast_map, - &expanded_crate, &arenas, id, control.make_glob_map, @@ -598,6 +597,10 @@ pub fn phase_2_configure_and_expand(sess: &Session, sess.abort_if_errors(); }); + time(time_passes, "early lint checks", || { + lint::check_ast_crate(sess, &krate) + }); + Some(krate) } @@ -641,7 +644,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, @@ -765,7 +767,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_lint/builtin.rs b/src/librustc_lint/builtin.rs index 816b84f3d46b1..c092049258c9b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -38,7 +38,7 @@ 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, LintContext, LintPass, LintArray, Lint}; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -73,7 +73,7 @@ impl LintPass for WhileTrue { lint_array!(WHILE_TRUE) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + 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 { @@ -122,7 +122,7 @@ impl LintPass for TypeLimits { lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnNeg, ref expr) => { match expr.node { @@ -377,7 +377,7 @@ 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, @@ -398,7 +398,7 @@ declare_lint! { } struct ImproperCTypesVisitor<'a, 'tcx: 'a> { - cx: &'a Context<'a, 'tcx> + cx: &'a LateContext<'a, 'tcx> } enum FfiResult { @@ -703,13 +703,13 @@ impl LintPass for ImproperCTypes { lint_array!(IMPROPER_CTYPES) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { - fn check_ty(cx: &Context, ty: &hir::Ty) { + 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 +747,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 { @@ -763,7 +763,7 @@ impl LintPass for BoxPointers { lint_array!(BOX_POINTERS) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) | hir::ItemTy(..) | @@ -786,7 +786,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 +799,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> { @@ -832,7 +832,7 @@ impl LintPass for RawPointerDerive { lint_array!(RAW_POINTER_DERIVE) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !attr::contains_name(&item.attrs, "automatically_derived") { return; } @@ -888,7 +888,7 @@ impl LintPass for UnusedAttributes { lint_array!(UNUSED_ATTRIBUTES) } - fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) { + 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 { @@ -948,7 +948,7 @@ impl LintPass for PathStatements { lint_array!(PATH_STATEMENTS) } - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { match s.node { hir::StmtSemi(ref expr, _) => { match expr.node { @@ -982,7 +982,7 @@ impl LintPass for UnusedResults { lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS) } - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { hir::StmtSemi(ref expr, _) => &**expr, _ => return @@ -1015,7 +1015,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 +1046,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() { @@ -1088,7 +1088,7 @@ impl LintPass for NonCamelCaseTypes { lint_array!(NON_CAMEL_CASE_TYPES) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + 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 +1119,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 +1127,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 +1190,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; @@ -1234,7 +1234,7 @@ impl LintPass for NonSnakeCase { lint_array!(NON_SNAKE_CASE) } - fn check_crate(&mut self, cx: &Context, cr: &hir::Crate) { + 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 +1244,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 +1264,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 +1291,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 +1312,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()) { @@ -1335,7 +1335,7 @@ impl LintPass for NonUpperCaseGlobals { lint_array!(NON_UPPER_CASE_GLOBALS) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { // only check static constants hir::ItemStatic(_, hir::MutImmutable, _) => { @@ -1348,7 +1348,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 +1358,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 +1368,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,7 +1390,7 @@ 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: &LateContext, value: &hir::Expr, msg: &str, struct_lit_needs_parens: bool) { if let hir::ExprParen(ref inner) = value.node { let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); @@ -1441,7 +1441,7 @@ impl LintPass for UnusedParens { lint_array!(UNUSED_PARENS) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::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), @@ -1459,7 +1459,7 @@ impl LintPass for UnusedParens { 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: &LateContext, s: &hir::Stmt) { let (value, msg) = match s.node { hir::StmtDecl(ref decl, _) => match decl.node { hir::DeclLocal(ref local) => match local.init { @@ -1488,7 +1488,7 @@ impl LintPass for UnusedImportBraces { lint_array!(UNUSED_IMPORT_BRACES) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + 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 { @@ -1518,7 +1518,7 @@ impl LintPass for NonShorthandFieldPatterns { lint_array!(NON_SHORTHAND_FIELD_PATTERNS) } - fn check_pat(&mut self, cx: &Context, pat: &hir::Pat) { + 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| { @@ -1557,7 +1557,7 @@ impl LintPass for UnusedUnsafe { lint_array!(UNUSED_UNSAFE) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + 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) && @@ -1582,7 +1582,7 @@ impl LintPass for UnsafeCode { lint_array!(UNSAFE_CODE) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + 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 +1591,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 +1603,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 +1619,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 +1639,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 @@ -1673,7 +1673,7 @@ impl LintPass for UnusedMut { lint_array!(UNUSED_MUT) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + 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 +1681,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 +1689,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 { @@ -1712,7 +1712,7 @@ impl LintPass for UnusedAllocation { lint_array!(UNUSED_ALLOCATION) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnUniq, _) => (), _ => return @@ -1774,7 +1774,7 @@ impl MissingDoc { } fn check_missing_docs_attrs(&self, - cx: &Context, + cx: &LateContext, id: Option, attrs: &[ast::Attribute], sp: Span, @@ -1817,7 +1817,7 @@ impl LintPass for MissingDoc { lint_array!(MISSING_DOCS) } - fn enter_lint_attrs(&mut self, _: &Context, attrs: &[ast::Attribute]) { + 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 +1827,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 +1886,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 +1900,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 +1916,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 +1928,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; } @@ -1954,7 +1954,7 @@ impl LintPass for MissingCopyImplementations { lint_array!(MISSING_COPY_IMPLEMENTATIONS) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; } @@ -2016,7 +2016,7 @@ impl LintPass for MissingDebugImplementations { lint_array!(MISSING_DEBUG_IMPLEMENTATIONS) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; } @@ -2066,7 +2066,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 +2077,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), .. }) => { @@ -2110,28 +2110,28 @@ impl LintPass for Stability { lint_array!(DEPRECATED) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + 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, @@ -2154,7 +2154,7 @@ impl LintPass for UnconditionalRecursion { lint_array![UNCONDITIONAL_RECURSION] } - fn check_fn(&mut self, cx: &Context, fn_kind: FnKind, _: &hir::FnDecl, + 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; @@ -2401,7 +2401,7 @@ impl LintPass for PluginAsLibrary { lint_array![PLUGIN_AS_LIBRARY] } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + 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; @@ -2457,7 +2457,7 @@ impl LintPass for InvalidNoMangleItems { NO_MANGLE_CONST_ITEMS) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) => { if attr::contains_name(&it.attrs, "no_mangle") && @@ -2503,7 +2503,7 @@ impl LintPass for MutableTransmutes { lint_array!(MUTABLE_TRANSMUTES) } - fn check_expr(&mut self, cx: &Context, expr: &hir::Expr) { + 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 +2518,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 +2542,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 +2569,8 @@ impl LintPass for UnstableFeatures { fn get_lints(&self) -> LintArray { lint_array!(UNSTABLE_FEATURES) } - fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) { + + 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 +2596,7 @@ impl LintPass for DropWithReprExtern { fn get_lints(&self) -> LintArray { lint_array!(DROP_WITH_REPR_EXTERN) } - fn check_crate(&mut self, ctx: &Context, _: &hir::Crate) { + 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/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, From 70c6fb91938fb15c8814b47c402dc08b79108670 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 10 Sep 2015 16:49:15 +1200 Subject: [PATCH 19/61] Change the unused parens lint to operate on the AST --- src/librustc_lint/builtin.rs | 56 ++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c092049258c9b..ba0d41240e13b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -38,7 +38,7 @@ 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, LateContext, LintContext, LintPass, LintArray, Lint}; +use lint::{Level, LateContext, EarlyContext, LintContext, LintPass, LintArray, Lint}; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -1390,9 +1390,9 @@ declare_lint! { pub struct UnusedParens; impl UnusedParens { - fn check_unused_parens_core(&self, cx: &LateContext, 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 +1405,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]) } @@ -1441,28 +1441,28 @@ impl LintPass for UnusedParens { lint_array!(UNUSED_PARENS) } - fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { + fn check_ast_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: &LateContext, s: &hir::Stmt) { + fn check_ast_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 }, From d21bfff78cd949ce72be57d3528c4f6985190feb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 10 Sep 2015 17:17:08 +1200 Subject: [PATCH 20/61] Remove hir::ExprParen --- src/librustc/middle/cfg/construct.rs | 1 - src/librustc/middle/check_const.rs | 2 -- src/librustc/middle/const_eval.rs | 1 - src/librustc/middle/expr_use_visitor.rs | 7 ------- src/librustc/middle/liveness.rs | 7 +++---- src/librustc/middle/mem_categorization.rs | 4 ---- src/librustc/middle/region.rs | 6 ++---- src/librustc_back/svh.rs | 2 -- src/librustc_front/fold.rs | 1 - src/librustc_front/hir.rs | 3 --- src/librustc_front/lowering.rs | 4 +++- src/librustc_front/print/pprust.rs | 5 ----- src/librustc_front/visit.rs | 3 --- src/librustc_lint/builtin.rs | 3 --- src/librustc_mir/build/expr/as_constant.rs | 3 --- src/librustc_mir/build/expr/as_lvalue.rs | 3 --- src/librustc_mir/build/expr/as_operand.rs | 14 ++++---------- src/librustc_mir/build/expr/as_rvalue.rs | 3 --- src/librustc_mir/build/expr/as_temp.rs | 14 ++++---------- src/librustc_mir/build/expr/category.rs | 4 +--- src/librustc_mir/build/expr/into.rs | 3 --- src/librustc_mir/hair.rs | 1 - src/librustc_mir/tcx/expr.rs | 2 -- src/librustc_trans/trans/consts.rs | 3 --- .../trans/debuginfo/create_scope_map.rs | 3 +-- src/librustc_trans/trans/expr.rs | 11 ----------- src/librustc_typeck/check/method/confirm.rs | 1 - src/librustc_typeck/check/mod.rs | 7 ------- 28 files changed, 18 insertions(+), 103 deletions(-) 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_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_front/fold.rs b/src/librustc_front/fold.rs index 0ff972f830f01..0693092c04a40 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -1164,7 +1164,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..8bc8bda9e066c 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 diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index 38f9ec2c8e6bc..4f5f892043b08 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -810,7 +810,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..d4a52a5ed8eb0 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -1556,11 +1556,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 ba0d41240e13b..556acf44b45d1 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -154,9 +154,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, 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_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..d8397b3c01766 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -630,9 +630,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 +931,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 +1044,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 +2741,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/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..e5dbfdf176739 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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); From c1084a3ada125b83c03c40b1f304f2f34abf0da0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 11 Sep 2015 20:15:58 +1200 Subject: [PATCH 21/61] Changes to tests --- src/librustc/lint/context.rs | 4 ++-- src/librustc_driver/driver.rs | 7 +++---- src/test/auxiliary/lint_for_crate.rs | 2 +- src/test/auxiliary/lint_group_plugin_test.rs | 2 +- src/test/auxiliary/lint_plugin_test.rs | 8 ++++---- src/test/compile-fail/autoderef-full-lval.rs | 1 - src/test/compile-fail/borrow-tuple-fields.rs | 1 - src/test/compile-fail/cast-as-bool.rs | 2 +- src/test/compile-fail/dropck_arr_cycle_checked.rs | 1 - src/test/compile-fail/dropck_tarena_cycle_checked.rs | 2 -- src/test/compile-fail/dropck_tarena_unsound_drop.rs | 2 -- src/test/compile-fail/dropck_vec_cycle_checked.rs | 1 - src/test/compile-fail/for-loop-hygiene.rs | 2 -- src/test/compile-fail/issue-17283.rs | 2 ++ src/test/compile-fail/issue-23729.rs | 2 +- src/test/compile-fail/lint-visible-private-types.rs | 1 - src/test/compile-fail/loop-does-not-diverge.rs | 2 +- src/test/compile-fail/variance-trait-bounds.rs | 1 - src/test/compile-fail/variance-types.rs | 1 - .../compile-fail/vec-must-not-hide-type-from-dropck.rs | 1 - src/test/pretty/issue-4264.pp | 7 +++---- src/test/run-make/execution-engine/test.rs | 2 +- 22 files changed, 20 insertions(+), 34 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 3f1a1ed48a147..7004dac3d4f40 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -505,10 +505,10 @@ pub trait LintContext: Sized { 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. + // 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, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 4ec13ba35993d..ff2780918f7bd 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -129,6 +129,9 @@ 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, @@ -597,10 +600,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, sess.abort_if_errors(); }); - time(time_passes, "early lint checks", || { - lint::check_ast_crate(sess, &krate) - }); - Some(krate) } diff --git a/src/test/auxiliary/lint_for_crate.rs b/src/test/auxiliary/lint_for_crate.rs index 4c9c7f443c290..927b3e1cba988 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::{Context, LintContext, LintPass, LintPassObject, LintArray}; use rustc::plugin::Registry; use rustc_front::hir; use syntax::attr; diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index adc194fa45486..45393913578e5 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::{Context, LintContext, LintPass, LintPassObject, LintArray}; use rustc::plugin::Registry; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/src/test/auxiliary/lint_plugin_test.rs b/src/test/auxiliary/lint_plugin_test.rs index e6f91db230009..0dedd78abee05 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -13,15 +13,15 @@ #![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, LintPassObject, LintArray}; use rustc::plugin::Registry; -use rustc_front::hir; +use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); struct Pass; @@ -31,7 +31,7 @@ impl LintPass for Pass { lint_array!(TEST_LINT) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_ast_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name == "lintme" { cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); } 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/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-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/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/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/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/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); From a642d853aa29f8ec8486e736be551cf77f34e219 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Sep 2015 11:35:25 +1200 Subject: [PATCH 22/61] Change to a multi-trait approach [breaking-change] for lint authors You must now implement LateLintPass or EarlyLintPass as well as LintPass and use either register_late_lint_pass or register_early_lint_pass, rather than register_lint_pass. --- src/librustc/lint/builtin.rs | 4 +- src/librustc/lint/context.rs | 167 +++++++++++-------- src/librustc/lint/mod.rs | 106 ++++++------ src/librustc/plugin/registry.rs | 18 +- src/librustc_driver/driver.rs | 9 +- src/librustc_lint/builtin.rs | 64 ++++++- src/librustc_lint/lib.rs | 19 ++- src/test/auxiliary/lint_for_crate.rs | 8 +- src/test/auxiliary/lint_group_plugin_test.rs | 8 +- src/test/auxiliary/lint_plugin_test.rs | 9 +- src/test/compile-fail/issue-23046.rs | 4 +- 11 files changed, 266 insertions(+), 150 deletions(-) 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 7004dac3d4f40..fe88401a24c20 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; @@ -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>, @@ -272,8 +293,6 @@ pub struct LateContext<'a, 'tcx: 'a> { node_levels: RefCell>, } -pub type Context<'a, 'tcx: 'a> = LateContext<'a, 'tcx>; - /// Context for lint checking of the AST, after expansion, before lowering to /// HIR. pub struct EarlyContext<'a> { @@ -293,14 +312,14 @@ pub struct EarlyContext<'a> { } /// 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.mut_lints().passes.take().unwrap(); + let mut passes = $cx.mut_lints().$ps.take().unwrap(); for obj in &mut passes { obj.$f($cx, $($args),*); } - $cx.mut_lints().passes = Some(passes); + $cx.mut_lints().$ps = Some(passes); }) } /// Parse the lint attributes into a vector, with `Err`s for malformed lint @@ -578,11 +597,11 @@ impl<'a, 'tcx> LintContext for LateContext<'a, 'tcx> { } fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { - run_lints!(self, enter_lint_attrs, attrs); + run_lints!(self, enter_lint_attrs, late_passes, attrs); } fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { - run_lints!(self, exit_lint_attrs, attrs); + run_lints!(self, exit_lint_attrs, late_passes, attrs); } } @@ -605,18 +624,18 @@ impl<'a> LintContext for EarlyContext<'a> { } fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { - run_lints!(self, ast_enter_lint_attrs, attrs); + run_lints!(self, enter_lint_attrs, early_passes, attrs); } fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { - run_lints!(self, ast_exit_lint_attrs, attrs); + 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)); hir_visit::walk_item(cx, it); }) @@ -624,29 +643,29 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { fn visit_foreign_item(&mut self, it: &hir::ForeignItem) { self.with_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_foreign_item, 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); + 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); + 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); + run_lints!(self, check_stmt, late_passes, s); hir_visit::walk_stmt(self, s); } 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); + run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body, span); } @@ -655,72 +674,72 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { ident: ast::Ident, g: &hir::Generics, id: ast::NodeId) { - run_lints!(self, check_struct_def, 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, s, ident, g, id); + 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); + 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); + run_lints!(cx, check_variant, late_passes, v, g); hir_visit::walk_variant(cx, v, g); - run_lints!(cx, check_variant_post, 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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)); hir_visit::walk_trait_item(cx, trait_item); }); @@ -728,43 +747,43 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { 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)); 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); + 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); + 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, attr); + 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_ast_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_ast_item, it); + run_lints!(cx, check_item, early_passes, it); cx.visit_ids(|v| v.visit_item(it)); ast_visit::walk_item(cx, it); }) @@ -772,29 +791,29 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { fn visit_foreign_item(&mut self, it: &ast::ForeignItem) { self.with_ast_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_ast_foreign_item, it); + 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_ast_pat, p); + 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_ast_expr, e); + 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_ast_stmt, s); + 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_ast_fn, fk, decl, body, span, id); + run_lints!(self, check_fn, early_passes, fk, decl, body, span, id); ast_visit::walk_fn(self, fk, decl, body, span); } @@ -803,72 +822,72 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { ident: ast::Ident, g: &ast::Generics, id: ast::NodeId) { - run_lints!(self, check_ast_struct_def, s, ident, g, id); + run_lints!(self, check_struct_def, early_passes, s, ident, g, id); ast_visit::walk_struct_def(self, s); - run_lints!(self, check_ast_struct_def_post, s, ident, g, id); + run_lints!(self, check_struct_def_post, early_passes, s, ident, g, id); } fn visit_struct_field(&mut self, s: &ast::StructField) { self.with_ast_lint_attrs(&s.node.attrs, |cx| { - run_lints!(cx, check_ast_struct_field, s); + 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_ast_lint_attrs(&v.node.attrs, |cx| { - run_lints!(cx, check_ast_variant, v, g); + run_lints!(cx, check_variant, early_passes, v, g); ast_visit::walk_variant(cx, v, g); - run_lints!(cx, check_ast_variant_post, v, g); + run_lints!(cx, check_variant_post, early_passes, v, g); }) } fn visit_ty(&mut self, t: &ast::Ty) { - run_lints!(self, check_ast_ty, t); + 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_ast_ident, sp, id); + 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_ast_mod, m, s, n); + 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_ast_local, l); + 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_ast_block, b); + 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_ast_arm, a); + 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_ast_decl, d); + 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_ast_expr_post, e); + run_lints!(self, check_expr_post, early_passes, e); } fn visit_generics(&mut self, g: &ast::Generics) { - run_lints!(self, check_ast_generics, g); + 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_ast_lint_attrs(&trait_item.attrs, |cx| { - run_lints!(cx, check_ast_trait_item, trait_item); + 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); }); @@ -876,36 +895,36 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { self.with_ast_lint_attrs(&impl_item.attrs, |cx| { - run_lints!(cx, check_ast_impl_item, impl_item); + 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_ast_opt_lifetime_ref, sp, lt); + run_lints!(self, check_opt_lifetime_ref, early_passes, sp, lt); } fn visit_lifetime_ref(&mut self, lt: &ast::Lifetime) { - run_lints!(self, check_ast_lifetime_ref, lt); + run_lints!(self, check_lifetime_ref, early_passes, lt); } fn visit_lifetime_def(&mut self, lt: &ast::LifetimeDef) { - run_lints!(self, check_ast_lifetime_def, lt); + run_lints!(self, check_lifetime_def, early_passes, lt); } fn visit_explicit_self(&mut self, es: &ast::ExplicitSelf) { - run_lints!(self, check_ast_explicit_self, es); + 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_ast_path, p, id); + 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_ast_attribute, attr); + run_lints!(self, check_attribute, early_passes, attr); } } @@ -946,7 +965,9 @@ impl LintPass for GatherNodeLevels { fn get_lints(&self) -> LintArray { lint_array!() } +} +impl LateLintPass for GatherNodeLevels { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemEnum(..) => { @@ -984,7 +1005,7 @@ pub fn check_crate(tcx: &ty::ctxt, // 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); hir_visit::walk_crate(cx, krate); }); @@ -1015,7 +1036,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // since the root module isn't visited as an item (because it isn't an // item), warn for it here. - run_lints!(cx, check_ast_crate, krate); + run_lints!(cx, check_crate, early_passes, krate); ast_visit::walk_crate(cx, krate); }); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index d30f8f3c53ad2..e52b6e91f68cd 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -39,7 +39,7 @@ use syntax::visit as ast_visit; use syntax::ast; use rustc_front::hir; -pub use lint::context::{LateContext, EarlyContext, Context, LintContext, LintStore, +pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, raw_emit_lint, check_crate, check_ast_crate, gather_attrs, GatherNodeLevels}; @@ -111,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. /// @@ -127,7 +119,18 @@ 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; +} + +/// 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) { } @@ -164,60 +167,63 @@ pub trait LintPass { fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { } fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { } - fn check_ast_ident(&mut self, _: &EarlyContext, _: Span, _: ast::Ident) { } - fn check_ast_crate(&mut self, _: &EarlyContext, _: &ast::Crate) { } - fn check_ast_mod(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { } - fn check_ast_foreign_item(&mut self, _: &EarlyContext, _: &ast::ForeignItem) { } - fn check_ast_item(&mut self, _: &EarlyContext, _: &ast::Item) { } - fn check_ast_local(&mut self, _: &EarlyContext, _: &ast::Local) { } - fn check_ast_block(&mut self, _: &EarlyContext, _: &ast::Block) { } - fn check_ast_stmt(&mut self, _: &EarlyContext, _: &ast::Stmt) { } - fn check_ast_arm(&mut self, _: &EarlyContext, _: &ast::Arm) { } - fn check_ast_pat(&mut self, _: &EarlyContext, _: &ast::Pat) { } - fn check_ast_decl(&mut self, _: &EarlyContext, _: &ast::Decl) { } - fn check_ast_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { } - fn check_ast_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { } - fn check_ast_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { } - fn check_ast_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { } - fn check_ast_fn(&mut self, _: &EarlyContext, - _: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { } - fn check_ast_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { } - fn check_ast_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { } - fn check_ast_struct_def(&mut self, _: &EarlyContext, - _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } - fn check_ast_struct_def_post(&mut self, _: &EarlyContext, - _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } - fn check_ast_struct_field(&mut self, _: &EarlyContext, _: &ast::StructField) { } - fn check_ast_variant(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } - fn check_ast_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } - fn check_ast_opt_lifetime_ref(&mut self, - _: &EarlyContext, - _: Span, - _: &Option) { } - fn check_ast_lifetime_ref(&mut self, _: &EarlyContext, _: &ast::Lifetime) { } - fn check_ast_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { } - fn check_ast_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { } - fn check_ast_mac(&mut self, _: &EarlyContext, _: &ast::Mac) { } - fn check_ast_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { } - fn check_ast_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, _: &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 ast_enter_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } + fn enter_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } - /// Counterpart to `ast_enter_lint_attrs`. - fn ast_exit_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } + /// Counterpart to `enter_lint_attrs`. + 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/plugin/registry.rs b/src/librustc/plugin/registry.rs index ca7ce2308a1cb..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!(), @@ -117,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_driver/driver.rs b/src/librustc_driver/driver.rs index ff2780918f7bd..ec5ceadd0662c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -482,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 { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 556acf44b45d1..394bd2abc08c7 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, LateContext, EarlyContext, LintContext, 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}; @@ -72,7 +73,9 @@ impl LintPass for WhileTrue { fn get_lints(&self) -> LintArray { lint_array!(WHILE_TRUE) } +} +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 { @@ -121,7 +124,9 @@ impl LintPass for TypeLimits { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS) } +} +impl LateLintPass for TypeLimits { fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnNeg, ref expr) => { @@ -699,7 +704,9 @@ impl LintPass for ImproperCTypes { fn get_lints(&self) -> LintArray { lint_array!(IMPROPER_CTYPES) } +} +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 }; @@ -759,7 +766,9 @@ impl LintPass for BoxPointers { fn get_lints(&self) -> LintArray { lint_array!(BOX_POINTERS) } +} +impl LateLintPass for BoxPointers { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) | @@ -828,7 +837,9 @@ impl LintPass for RawPointerDerive { fn get_lints(&self) -> LintArray { lint_array!(RAW_POINTER_DERIVE) } +} +impl LateLintPass for RawPointerDerive { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !attr::contains_name(&item.attrs, "automatically_derived") { return; @@ -884,7 +895,9 @@ impl LintPass for UnusedAttributes { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_ATTRIBUTES) } +} +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 { @@ -944,7 +957,9 @@ impl LintPass for PathStatements { fn get_lints(&self) -> LintArray { lint_array!(PATH_STATEMENTS) } +} +impl LateLintPass for PathStatements { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { match s.node { hir::StmtSemi(ref expr, _) => { @@ -978,7 +993,9 @@ impl LintPass for UnusedResults { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS) } +} +impl LateLintPass for UnusedResults { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { hir::StmtSemi(ref expr, _) => &**expr, @@ -1084,7 +1101,9 @@ impl LintPass for NonCamelCaseTypes { fn get_lints(&self) -> LintArray { lint_array!(NON_CAMEL_CASE_TYPES) } +} +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() @@ -1230,7 +1249,9 @@ impl LintPass for NonSnakeCase { fn get_lints(&self) -> LintArray { lint_array!(NON_SNAKE_CASE) } +} +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))); @@ -1331,7 +1352,9 @@ impl LintPass for NonUpperCaseGlobals { fn get_lints(&self) -> LintArray { lint_array!(NON_UPPER_CASE_GLOBALS) } +} +impl LateLintPass for NonUpperCaseGlobals { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { // only check static constants @@ -1437,8 +1460,10 @@ impl LintPass for UnusedParens { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_PARENS) } +} - fn check_ast_expr(&mut self, cx: &EarlyContext, e: &ast::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 { ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), @@ -1456,7 +1481,7 @@ impl LintPass for UnusedParens { self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens); } - fn check_ast_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { + fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { let (value, msg) = match s.node { ast::StmtDecl(ref decl, _) => match decl.node { ast::DeclLocal(ref local) => match local.init { @@ -1484,7 +1509,9 @@ impl LintPass for UnusedImportBraces { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_IMPORT_BRACES) } +} +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 { @@ -1514,7 +1541,9 @@ impl LintPass for NonShorthandFieldPatterns { fn get_lints(&self) -> LintArray { lint_array!(NON_SHORTHAND_FIELD_PATTERNS) } +} +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 { @@ -1553,7 +1582,9 @@ impl LintPass for UnusedUnsafe { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_UNSAFE) } +} +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. @@ -1578,7 +1609,9 @@ impl LintPass for UnsafeCode { fn get_lints(&self) -> LintArray { lint_array!(UNSAFE_CODE) } +} +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. @@ -1669,7 +1702,9 @@ impl LintPass for UnusedMut { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_MUT) } +} +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 { @@ -1708,7 +1743,9 @@ impl LintPass for UnusedAllocation { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_ALLOCATION) } +} +impl LateLintPass for UnusedAllocation { fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnUniq, _) => (), @@ -1813,7 +1850,9 @@ impl LintPass for MissingDoc { fn get_lints(&self) -> LintArray { lint_array!(MISSING_DOCS) } +} +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() { @@ -1950,7 +1989,9 @@ impl LintPass for MissingCopyImplementations { fn get_lints(&self) -> LintArray { lint_array!(MISSING_COPY_IMPLEMENTATIONS) } +} +impl LateLintPass for MissingCopyImplementations { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; @@ -2012,7 +2053,9 @@ impl LintPass for MissingDebugImplementations { fn get_lints(&self) -> LintArray { lint_array!(MISSING_DEBUG_IMPLEMENTATIONS) } +} +impl LateLintPass for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; @@ -2106,7 +2149,9 @@ impl LintPass for Stability { fn get_lints(&self) -> LintArray { lint_array!(DEPRECATED) } +} +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| @@ -2150,7 +2195,9 @@ impl LintPass for UnconditionalRecursion { fn get_lints(&self) -> LintArray { lint_array![UNCONDITIONAL_RECURSION] } +} +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>, @@ -2397,7 +2444,9 @@ impl LintPass for PluginAsLibrary { fn get_lints(&self) -> LintArray { lint_array![PLUGIN_AS_LIBRARY] } +} +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. @@ -2453,7 +2502,9 @@ impl LintPass for InvalidNoMangleItems { PRIVATE_NO_MANGLE_STATICS, NO_MANGLE_CONST_ITEMS) } +} +impl LateLintPass for InvalidNoMangleItems { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) => { @@ -2499,7 +2550,9 @@ impl LintPass for MutableTransmutes { fn get_lints(&self) -> LintArray { lint_array!(MUTABLE_TRANSMUTES) } +} +impl LateLintPass for MutableTransmutes { fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { use syntax::abi::RustIntrinsic; @@ -2566,7 +2619,9 @@ impl LintPass for UnstableFeatures { fn get_lints(&self) -> LintArray { lint_array!(UNSTABLE_FEATURES) } +} +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() { @@ -2593,6 +2648,9 @@ impl LintPass for DropWithReprExtern { fn get_lints(&self) -> LintArray { lint_array!(DROP_WITH_REPR_EXTERN) } +} + +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) = 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/test/auxiliary/lint_for_crate.rs b/src/test/auxiliary/lint_for_crate.rs index 927b3e1cba988..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, LintContext, 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 45393913578e5..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, LintContext, 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 0dedd78abee05..4f5e8d6e0874c 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -19,7 +19,8 @@ extern crate syntax; #[macro_use] extern crate rustc; -use rustc::lint::{EarlyContext, LintContext, LintPass, LintPassObject, LintArray}; +use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, + EarlyLintPassObject, LintArray}; use rustc::plugin::Registry; use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); @@ -30,8 +31,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(TEST_LINT) } +} - fn check_ast_item(&mut self, cx: &EarlyContext, it: &ast::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/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)})}; } From ed61a64a957d5c13cc524f9d516ac3626861717f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Sep 2015 17:31:33 +1200 Subject: [PATCH 23/61] rebasing --- src/librustc/lint/context.rs | 34 +++++++++++++--------------------- src/librustc/middle/ty/mod.rs | 2 -- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index fe88401a24c20..9a736747d5291 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -408,8 +408,8 @@ pub trait LintContext: Sized { 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: &[hir::Attribute]); - fn exit_attrs(&mut self, attrs: &[hir::Attribute]); + 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. @@ -510,14 +510,6 @@ pub trait LintContext: Sized { self.mut_lints().set_level(lint, lvlsrc); } } - - fn with_ast_lint_attrs(&mut self, - attrs: &[ast::Attribute], - f: F) - where F: FnOnce(&mut Self), - { - self.with_lint_attrs(&lower_attrs(attrs), f) - } } @@ -596,11 +588,11 @@ impl<'a, 'tcx> LintContext for LateContext<'a, 'tcx> { &mut self.level_stack } - fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { + fn enter_attrs(&mut self, attrs: &[ast::Attribute]) { run_lints!(self, enter_lint_attrs, late_passes, attrs); } - fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { + fn exit_attrs(&mut self, attrs: &[ast::Attribute]) { run_lints!(self, exit_lint_attrs, late_passes, attrs); } } @@ -623,11 +615,11 @@ impl<'a> LintContext for EarlyContext<'a> { &mut self.level_stack } - fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { + fn enter_attrs(&mut self, attrs: &[ast::Attribute]) { run_lints!(self, enter_lint_attrs, early_passes, attrs); } - fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { + fn exit_attrs(&mut self, attrs: &[ast::Attribute]) { run_lints!(self, exit_lint_attrs, early_passes, attrs); } } @@ -782,7 +774,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { fn visit_item(&mut self, it: &ast::Item) { - self.with_ast_lint_attrs(&it.attrs, |cx| { + 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); @@ -790,7 +782,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { } fn visit_foreign_item(&mut self, it: &ast::ForeignItem) { - self.with_ast_lint_attrs(&it.attrs, |cx| { + self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_foreign_item, early_passes, it); ast_visit::walk_foreign_item(cx, it); }) @@ -828,14 +820,14 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { } fn visit_struct_field(&mut self, s: &ast::StructField) { - self.with_ast_lint_attrs(&s.node.attrs, |cx| { + 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_ast_lint_attrs(&v.node.attrs, |cx| { + 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); @@ -886,7 +878,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { } fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { - self.with_ast_lint_attrs(&trait_item.attrs, |cx| { + 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); @@ -894,7 +886,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { } fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { - self.with_ast_lint_attrs(&impl_item.attrs, |cx| { + 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); @@ -1027,7 +1019,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { let mut cx = EarlyContext::new(sess, krate); // Visit the whole crate. - cx.with_ast_lint_attrs(&krate.attrs, |cx| { + cx.with_lint_attrs(&krate.attrs, |cx| { cx.visit_id(ast::CRATE_NODE_ID); cx.visit_ids(|v| { v.visited_outermost = true; 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), } } From 69fdc0fa49c5dc3e7e58f11931261cc872dda5e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Inf=C3=BChr?= Date: Wed, 16 Sep 2015 18:01:46 -0700 Subject: [PATCH 24/61] corrected link to Hasher --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index e8ce773ceff81..8d28535f62376 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -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 From 61cb1baab1616134ff77af7ac290ab8f97d6927f Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Thu, 10 Sep 2015 21:47:57 +1200 Subject: [PATCH 25/61] Add compiler option to keep mtwt tables This is so that the resolution results can be used after analysis, potentially for tool support --- src/librustc/session/config.rs | 2 ++ src/librustc_driver/driver.rs | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) 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_driver/driver.rs b/src/librustc_driver/driver.rs index f3038624ac107..7d0f1b44d23c7 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -671,7 +671,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)); From 4fbe5149856e4de2dc74ef4a5ae7c7903e388117 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 17 Sep 2015 15:13:51 +1200 Subject: [PATCH 26/61] Fix the span for ! returns --- src/libsyntax/parse/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ff622859cf0b1..b6650b6f94420 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()))) } From e3be84c6c81c63e11f62105a9befcc39b9a17081 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 16 Sep 2015 19:35:33 +0300 Subject: [PATCH 27/61] libsyntax: forbid visibility modifiers for enum variants fixes #28433 --- src/libsyntax/parse/parser.rs | 7 ++----- .../{issue-3993-2.rs => issue-28433.rs} | 14 +++++--------- .../{useless-priv.rs => useless-pub.rs} | 1 - 3 files changed, 7 insertions(+), 15 deletions(-) rename src/test/compile-fail/{issue-3993-2.rs => issue-28433.rs} (65%) rename src/test/compile-fail/{useless-priv.rs => useless-pub.rs} (91%) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ff622859cf0b1..4c25714093481 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5200,13 +5200,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 +5245,7 @@ impl<'a> Parser<'a> { kind: kind, id: ast::DUMMY_NODE_ID, disr_expr: disr_expr, - vis: vis, + vis: Inherited, }; variants.push(P(spanned(vlo, self.last_span.hi, vr))); diff --git a/src/test/compile-fail/issue-3993-2.rs b/src/test/compile-fail/issue-28433.rs similarity index 65% rename from src/test/compile-fail/issue-3993-2.rs rename to src/test/compile-fail/issue-28433.rs index 9d9e91a141be3..ab0708c28aef6 100644 --- a/src/test/compile-fail/issue-3993-2.rs +++ b/src/test/compile-fail/issue-28433.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,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use zoo::bird::{duck, goose}; - -mod zoo { - pub enum bird { - pub duck, //~ ERROR: unnecessary `pub` visibility - goose - } +enum bird { + pub duck, //~ ERROR: expected identifier, found keyword `pub` + goose } fn main() { - let y = goose; + let y = bird::goose; } 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); From f5a99ae7fb43fd44512e2f9294c2c186e776ed36 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 16 Sep 2015 20:01:15 +0300 Subject: [PATCH 28/61] Remove Visibility field from enum variants Followup on #28440 --- src/librustc_front/fold.rs | 3 +-- src/librustc_front/hir.rs | 1 - src/librustc_front/lowering.rs | 1 - src/librustc_front/print/pprust.rs | 1 - src/librustc_privacy/lib.rs | 21 ++------------------- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/doctree.rs | 1 - src/librustdoc/visit_ast.rs | 1 - src/libsyntax/ast.rs | 1 - src/libsyntax/config.rs | 3 +-- src/libsyntax/ext/build.rs | 1 - src/libsyntax/fold.rs | 3 +-- src/libsyntax/parse/parser.rs | 1 - src/libsyntax/print/pprust.rs | 4 +--- 14 files changed, 7 insertions(+), 37 deletions(-) diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index 0ff972f830f01..8ee13a408465d 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), }) diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index f329aa49daabc..8a4cfa28c1d4d 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -1055,7 +1055,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..aeaf20cd9d081 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, }) diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index d8d85135dd8f5..4231a7c69b18a 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)); 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/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/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/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/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/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 4c25714093481..d4f7509e0c337 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5245,7 +5245,6 @@ impl<'a> Parser<'a> { kind: kind, id: ast::DUMMY_NODE_ID, disr_expr: disr_expr, - vis: Inherited, }; 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..8d92eaffb9eb6 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)); @@ -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] From 7ff85cd216c175a65ef1802891243998ca3d9fca Mon Sep 17 00:00:00 2001 From: Vitali Haravy Date: Thu, 17 Sep 2015 12:03:27 +0300 Subject: [PATCH 29/61] Correct type definition of HANDLE. --- src/test/run-pass/x86stdcall2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From a9cb51cf0cf8adc8188097c019daeaf10822d20f Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 17 Sep 2015 12:47:03 +0300 Subject: [PATCH 30/61] Fix test expectations because of #28439 --- src/test/compile-fail/issue-28433.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/compile-fail/issue-28433.rs b/src/test/compile-fail/issue-28433.rs index ab0708c28aef6..3ca2213087d1f 100644 --- a/src/test/compile-fail/issue-28433.rs +++ b/src/test/compile-fail/issue-28433.rs @@ -9,7 +9,9 @@ // except according to those terms. enum bird { - pub duck, //~ ERROR: expected identifier, found keyword `pub` + pub duck, + //~^ ERROR: expected identifier, found keyword `pub` + //~^^ ERROR: expected goose } From 6def06c973b3aded197789c4b02d20ad378165f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Wed, 16 Sep 2015 01:26:58 +0200 Subject: [PATCH 31/61] Don't create adjustments from a type to itself Currently, we're generating adjustments, for example, to get from &[u8] to &[u8], which is unneeded and kicks us out of trans_into() into trans() which means an additional stack slot and copy in the unoptimized code. --- src/librustc_typeck/check/coercion.rs | 4 ++++ src/test/codegen/adjustments.rs | 28 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/codegen/adjustments.rs diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 65409afa52d10..dd84bfb4099bd 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -107,6 +107,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/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs new file mode 100644 index 0000000000000..b0438f561b935 --- /dev/null +++ b/src/test/codegen/adjustments.rs @@ -0,0 +1,28 @@ +// 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 } +} From 83b5370d5dca8b602621be1651e44b6ed4d26386 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Thu, 17 Sep 2015 09:30:43 -0400 Subject: [PATCH 32/61] Add tests for #23543, #23544 Closes #23543. Closes #23544. --- src/test/compile-fail/issue-23543.rs | 21 +++++++++++++++++++++ src/test/compile-fail/issue-23544.rs | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/test/compile-fail/issue-23543.rs create mode 100644 src/test/compile-fail/issue-23544.rs diff --git a/src/test/compile-fail/issue-23543.rs b/src/test/compile-fail/issue-23543.rs new file mode 100644 index 0000000000000..4ed44154c4748 --- /dev/null +++ b/src/test/compile-fail/issue-23543.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. + +pub trait A: Copy {} + +struct Foo; + +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-23544.rs b/src/test/compile-fail/issue-23544.rs new file mode 100644 index 0000000000000..1d7c2187045ea --- /dev/null +++ b/src/test/compile-fail/issue-23544.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait A: Copy {} + +pub trait D { + fn f(self) + where T: A; + //~^ ERROR associated type bindings are not allowed here [E0229] +} + +fn main() {} From 0675dffac48101faa2bdb634682b2ddf3975bf31 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 26 Aug 2015 16:57:56 -0700 Subject: [PATCH 33/61] rmake: Get all tests passing on MSVC --- mk/tests.mk | 9 +++- src/etc/maketest.py | 12 +++++- .../run-make/archive-duplicate-names/Makefile | 4 +- src/test/run-make/c-dynamic-dylib/cfoo.c | 3 ++ src/test/run-make/c-dynamic-rlib/cfoo.c | 4 ++ .../run-make/c-link-to-rust-dylib/Makefile | 17 +++++--- .../c-link-to-rust-staticlib/Makefile | 6 +-- src/test/run-make/c-static-dylib/Makefile | 4 +- src/test/run-make/c-static-rlib/Makefile | 4 +- .../run-make/crate-name-priority/Makefile | 2 +- src/test/run-make/extern-fn-generic/Makefile | 8 ++-- src/test/run-make/extern-fn-mangle/Makefile | 6 +-- .../extern-fn-with-packed-struct/Makefile | 6 +-- .../extern-fn-with-packed-struct/test.c | 10 +++++ .../run-make/extern-fn-with-union/Makefile | 8 ++-- .../interdependent-c-libraries/Makefile | 2 +- src/test/run-make/issue-12446/Makefile | 2 +- src/test/run-make/issue-14500/Makefile | 2 +- src/test/run-make/issue-15460/Makefile | 2 +- src/test/run-make/issue-15460/foo.c | 4 ++ src/test/run-make/issue-15460/foo.rs | 2 + src/test/run-make/issue-25581/Makefile | 6 +-- src/test/run-make/issue-26092/Makefile | 2 +- src/test/run-make/link-path-order/Makefile | 8 ++-- .../run-make/linkage-attr-on-static/Makefile | 6 +-- .../run-make/linkage-attr-on-static/bar.rs | 1 + src/test/run-make/lto-smoke-c/Makefile | 4 +- src/test/run-make/no-duplicate-libs/Makefile | 5 +++ src/test/run-make/no-duplicate-libs/bar.c | 4 -- src/test/run-make/no-duplicate-libs/foo.c | 2 - .../output-type-permutations/Makefile | 14 ++++--- src/test/run-make/relocation-model/Makefile | 14 +++++-- .../run-make/static-dylib-by-default/Makefile | 9 +++- src/test/run-make/tools.mk | 41 +++++++++++++++---- 34 files changed, 155 insertions(+), 78 deletions(-) delete mode 100644 src/test/run-make/no-duplicate-libs/bar.c delete mode 100644 src/test/run-make/no-duplicate-libs/foo.c 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/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/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/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-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,$@,$<) From 519527b1f58eaa572307b33ef69a837d4d49cdd0 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Thu, 17 Sep 2015 12:04:34 -0400 Subject: [PATCH 34/61] Remove empty test files It is likely that these were committed by mistake. --- src/test/run-make/allow-non-lint-warnings-cmdline/1 | 0 src/test/run-make/allow-warnings-cmdline-stability/1 | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/test/run-make/allow-non-lint-warnings-cmdline/1 delete mode 100644 src/test/run-make/allow-warnings-cmdline-stability/1 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 From 6d2cb6c688ce0a8aa309236dd04b45149f8eee3c Mon Sep 17 00:00:00 2001 From: Bastien Dejean Date: Thu, 17 Sep 2015 18:53:01 +0200 Subject: [PATCH 35/61] trpl: Fix off-by-one highest memory address --- src/doc/trpl/the-stack-and-the-heap.md | 172 ++++++++++++------------- 1 file changed, 86 insertions(+), 86 deletions(-) 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. From 25cc001c194ac9a1134a30a99ad721695c3c0e8c Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 17 Sep 2015 21:46:46 +0200 Subject: [PATCH 36/61] doc: no need to mention the method by name It's clear it's the one being documented --- src/libcore/ops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } From 553a2f1ead6e6c9be8b6d3b0a556a26141206715 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 17 Sep 2015 22:13:05 +0200 Subject: [PATCH 37/61] doc: follow idiom in code snippet --- src/doc/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 717c99901d1bc..efb986e19edfb 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2762,7 +2762,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 From 22fc5f480d5ec3caf1e6e7cd4192c946d488ff2a Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 17 Sep 2015 22:52:39 +0200 Subject: [PATCH 38/61] reference: mark that up to make it more clear it is a keyword --- src/doc/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 717c99901d1bc..6035f936c6ca3 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3087,7 +3087,7 @@ loops](#infinite-loops), [break expressions](#break-expressions), and 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; From a3305f87c154aae5e7b46f4525683567a0938455 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 17 Sep 2015 22:24:15 +0200 Subject: [PATCH 39/61] reference: actual keywords feel more appropriate --- src/doc/reference.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 717c99901d1bc..d7d9f938ed87b 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3035,10 +3035,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 +3046,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 +3059,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,7 +3082,7 @@ 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`. @@ -3117,7 +3117,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 +3129,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 +3235,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 +3256,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 +3264,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 From 5a91ba8e6028241558c5eb1a9405ede07bf306c6 Mon Sep 17 00:00:00 2001 From: Dongie Agnir Date: Thu, 17 Sep 2015 23:43:33 -0400 Subject: [PATCH 40/61] Fix spelling and remove weirdly placed comma. --- COMPILER_TESTS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 From cbc9517b023f3484816b59fd13993027c412748d Mon Sep 17 00:00:00 2001 From: Colin Wallace Date: Thu, 17 Sep 2015 21:39:19 -0700 Subject: [PATCH 41/61] Clarify where let accepts a pattern, spatially --- src/doc/trpl/guessing-game.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index 3a4328562f872..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: From 66f662f37de1ab689602d909761ad0f0745b4648 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 Sep 2015 16:41:11 +1200 Subject: [PATCH 42/61] Fix crash with --save-analysis Should be lowering ast expressions to HIR expressions, not cheating via the hir map. That goes wrong now that there is not a 1:1 mapping between ast and hir (in the case of the crash due to ExprParen). --- src/librustc_trans/save/dump_csv.rs | 2 +- src/librustc_trans/save/mod.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) 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); From 269c59d3414027c2194fb5deb1d26845d088afb9 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 Sep 2015 18:07:05 +1200 Subject: [PATCH 43/61] Warn on `pub extern crate`. Temporary 'fix' for #26775 --- src/libsyntax/parse/parser.rs | 17 ++++++++++++----- src/test/compile-fail/warn-pub-extern-crate.rs | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/warn-pub-extern-crate.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ff622859cf0b1..8d50cc099bd60 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5116,12 +5116,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 diff --git a/src/test/compile-fail/warn-pub-extern-crate.rs b/src/test/compile-fail/warn-pub-extern-crate.rs new file mode 100644 index 0000000000000..fec0b8e1a4cc1 --- /dev/null +++ b/src/test/compile-fail/warn-pub-extern-crate.rs @@ -0,0 +1,18 @@ +// 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. + +// Check that `pub extern crate` gives a warning. + + +pub extern crate core; //~WARN `pub extern crate` does not work +//~^ ERROR core + +fn main() { +} From da059a4e280595333f55bfccc983349a3b2e810d Mon Sep 17 00:00:00 2001 From: kud1ing Date: Fri, 18 Sep 2015 09:19:20 +0200 Subject: [PATCH 44/61] Add 1.3 release date As of http://blog.rust-lang.org/2015/09/17/Rust-1.3.html --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 8d28535f62376..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 From 5fa6e857c9f43a69661ebca278c99155ee7d5db7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Sep 2015 22:46:52 +0300 Subject: [PATCH 45/61] Implement empty struct with braces (RFC 218) --- src/librustc_front/print/pprust.rs | 50 +++++++++---------- src/librustc_typeck/check/mod.rs | 4 +- src/libsyntax/parse/parser.rs | 21 ++------ src/libsyntax/print/pprust.rs | 50 +++++++++---------- .../empty-struct-with-braces-1.rs} | 13 ++--- .../empty-struct-with-braces-2.rs} | 20 +++++--- src/test/compile-fail/issue-27831.rs | 4 +- src/test/parse-fail/struct-no-fields-4.rs | 20 -------- src/test/parse-fail/struct-no-fields-5.rs | 20 -------- src/test/run-pass/empty-struct-with-braces.rs | 31 ++++++++++++ .../issue-16819.rs} | 14 ++++-- 11 files changed, 114 insertions(+), 133 deletions(-) rename src/test/{parse-fail/struct-no-fields-2.rs => compile-fail/empty-struct-with-braces-1.rs} (62%) rename src/test/{parse-fail/struct-no-fields-3.rs => compile-fail/empty-struct-with-braces-2.rs} (52%) delete mode 100644 src/test/parse-fail/struct-no-fields-4.rs delete mode 100644 src/test/parse-fail/struct-no-fields-5.rs create mode 100644 src/test/run-pass/empty-struct-with-braces.rs rename src/test/{parse-fail/struct-no-fields.rs => run-pass/issue-16819.rs} (67%) diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index d4a52a5ed8eb0..940145aa4173b 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -1218,34 +1218,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(()) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e5dbfdf176739..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()); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b6650b6f94420..a7978babcb7e1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b00ff85051c9a..1d22c83122e51 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1855,34 +1855,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(()) } diff --git a/src/test/parse-fail/struct-no-fields-2.rs b/src/test/compile-fail/empty-struct-with-braces-1.rs similarity index 62% rename from src/test/parse-fail/struct-no-fields-2.rs rename to src/test/compile-fail/empty-struct-with-braces-1.rs index 1e6169f285b5c..bfe72856a2e17 100644 --- a/src/test/parse-fail/struct-no-fields-2.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,10 @@ // 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; +struct Empty {} -fn f2() { - let _end_stmt = Foo { }; - //~^ ERROR: structure literal must either have at least one field +fn main() { + let e = Empty; //~ ERROR `Empty` is the name of a struct or struct variant } - -fn main() {} diff --git a/src/test/parse-fail/struct-no-fields-3.rs b/src/test/compile-fail/empty-struct-with-braces-2.rs similarity index 52% rename from src/test/parse-fail/struct-no-fields-3.rs rename to src/test/compile-fail/empty-struct-with-braces-2.rs index 8e72151ffe979..7e5a87fe1a44e 100644 --- a/src/test/parse-fail/struct-no-fields-3.rs +++ b/src/test/compile-fail/empty-struct-with-braces-2.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,17 @@ // 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; +#![deny(warnings)] -fn g3() { - let _mid_tuple = (Foo { }, 2); - //~^ ERROR: structure literal must either have at least one field -} +struct Empty {} + +fn main() { + let e = Empty {}; -fn main() {} + 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/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/parse-fail/struct-no-fields-4.rs b/src/test/parse-fail/struct-no-fields-4.rs deleted file mode 100644 index 6e55baf06cedf..0000000000000 --- a/src/test/parse-fail/struct-no-fields-4.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 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: -Z parse-only - -struct Foo; - -fn h4() { - let _end_of_tuple = (3, Foo { }); - //~^ ERROR: structure literal must either have at least one field -} - -fn main() {} diff --git a/src/test/parse-fail/struct-no-fields-5.rs b/src/test/parse-fail/struct-no-fields-5.rs deleted file mode 100644 index 5f92d98606693..0000000000000 --- a/src/test/parse-fail/struct-no-fields-5.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 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: -Z parse-only - -struct Foo; - -fn i5() { - let _end_of_block = { Foo { } }; - //~^ ERROR: structure literal must either have at least one field -} - -fn main() {} 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..a96c1e5b10c4b --- /dev/null +++ b/src/test/run-pass/empty-struct-with-braces.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. + +// Empty struct defined with braces add names into type namespace +// Empty struct defined without braces add names into both type and value namespaces + +struct Empty1 {} +struct Empty2; + +fn main() { + let e1: Empty1 = Empty1 {}; + let e2: Empty2 = Empty2 {}; + let e2: Empty2 = Empty2; + + match e1 { + Empty1 {} => () + } + match e2 { + Empty2 {} => () + } + match e2 { + Empty2 => () + } +} diff --git a/src/test/parse-fail/struct-no-fields.rs b/src/test/run-pass/issue-16819.rs similarity index 67% rename from src/test/parse-fail/struct-no-fields.rs rename to src/test/run-pass/issue-16819.rs index fa5065b763027..fb35ce33157d6 100644 --- a/src/test/parse-fail/struct-no-fields.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,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +//`#[cfg]` on struct field permits empty unusable struct -struct Foo {} -//~^ ERROR: unit-like struct definition should be written as `struct Foo;` +struct S { + #[cfg(untrue)] + a: int, +} -fn main() {} +fn main() { + let s = S {}; +} From 605a4729481db73473dc37f09f840da6ec6173ab Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 11 Sep 2015 14:03:38 +0300 Subject: [PATCH 46/61] Add some more tests --- src/doc/reference.md | 13 +++++++++-- src/test/run-pass/empty-struct-with-braces.rs | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 18feebf3d5689..95a58686cf27e 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1178,11 +1178,20 @@ 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 structure implicitly defines a constant of +its type with the same name. For example: ``` struct Cookie; -let c = [Cookie, Cookie, Cookie, Cookie]; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; +``` + +is equivalent to + +``` +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 diff --git a/src/test/run-pass/empty-struct-with-braces.rs b/src/test/run-pass/empty-struct-with-braces.rs index a96c1e5b10c4b..6ed5f6954a017 100644 --- a/src/test/run-pass/empty-struct-with-braces.rs +++ b/src/test/run-pass/empty-struct-with-braces.rs @@ -13,11 +13,15 @@ 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 {} => () @@ -28,4 +32,23 @@ fn main() { 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 }; } From 1eb42f1c784e999259b15f68c63040e1fafbe273 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 18 Sep 2015 13:36:45 +0300 Subject: [PATCH 47/61] Add feature gate --- src/doc/reference.md | 5 ++++- src/libsyntax/feature_gate.rs | 21 ++++++++++++++++++- .../empty-struct-with-braces-1.rs | 2 ++ .../empty-struct-with-braces-2.rs | 1 + .../empty-struct-with-braces-3.rs | 21 +++++++++++++++++++ src/test/run-pass/empty-struct-with-braces.rs | 2 ++ src/test/run-pass/issue-16819.rs | 2 ++ 7 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/empty-struct-with-braces-3.rs diff --git a/src/doc/reference.md b/src/doc/reference.md index 95a58686cf27e..83849574260e1 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1178,10 +1178,11 @@ 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 structure implicitly defines a constant of +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 {}]; ``` @@ -1189,6 +1190,7 @@ 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 {}]; @@ -2420,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 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/test/compile-fail/empty-struct-with-braces-1.rs b/src/test/compile-fail/empty-struct-with-braces-1.rs index bfe72856a2e17..ad412259faa29 100644 --- a/src/test/compile-fail/empty-struct-with-braces-1.rs +++ b/src/test/compile-fail/empty-struct-with-braces-1.rs @@ -10,6 +10,8 @@ // Empty struct defined with braces shouldn't add names into value namespace +#![feature(braced_empty_structs)] + struct Empty {} fn main() { diff --git a/src/test/compile-fail/empty-struct-with-braces-2.rs b/src/test/compile-fail/empty-struct-with-braces-2.rs index 7e5a87fe1a44e..0e72e7dc44185 100644 --- a/src/test/compile-fail/empty-struct-with-braces-2.rs +++ b/src/test/compile-fail/empty-struct-with-braces-2.rs @@ -10,6 +10,7 @@ // Empty struct defined with braces shouldn't add names into value namespace +#![feature(braced_empty_structs)] #![deny(warnings)] struct 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/empty-struct-with-braces.rs b/src/test/run-pass/empty-struct-with-braces.rs index 6ed5f6954a017..dc806acb980dd 100644 --- a/src/test/run-pass/empty-struct-with-braces.rs +++ b/src/test/run-pass/empty-struct-with-braces.rs @@ -11,6 +11,8 @@ // 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 {} diff --git a/src/test/run-pass/issue-16819.rs b/src/test/run-pass/issue-16819.rs index fb35ce33157d6..a9abb99696f59 100644 --- a/src/test/run-pass/issue-16819.rs +++ b/src/test/run-pass/issue-16819.rs @@ -10,6 +10,8 @@ //`#[cfg]` on struct field permits empty unusable struct +#![feature(braced_empty_structs)] + struct S { #[cfg(untrue)] a: int, From 2c17bfc20cf2140adf2d7c3fff0f02db6799b93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Fri, 18 Sep 2015 15:46:58 +0200 Subject: [PATCH 48/61] Skip no-op adjustments in trans That allows us to keep using trans_into() in case of adjustments that may actually be ignored in trans because they are a plain deref/ref pair with no overloaded deref or unsizing. Unoptimized(!) benchmarks from servo/servo#7638 Before ``` test goser::bench_clone ... bench: 17,701 ns/iter (+/- 58) = 30 MB/s test goser::bincode::bench_decoder ... bench: 33,715 ns/iter (+/- 300) = 11 MB/s test goser::bincode::bench_deserialize ... bench: 36,804 ns/iter (+/- 329) = 9 MB/s test goser::bincode::bench_encoder ... bench: 34,695 ns/iter (+/- 149) = 11 MB/s test goser::bincode::bench_populate ... bench: 18,879 ns/iter (+/- 88) test goser::bincode::bench_serialize ... bench: 31,668 ns/iter (+/- 156) = 11 MB/s test goser::capnp::bench_deserialize ... bench: 2,049 ns/iter (+/- 87) = 218 MB/s test goser::capnp::bench_deserialize_packed ... bench: 10,707 ns/iter (+/- 258) = 31 MB/s test goser::capnp::bench_populate ... bench: 635 ns/iter (+/- 5) test goser::capnp::bench_serialize ... bench: 35,657 ns/iter (+/- 155) = 12 MB/s test goser::capnp::bench_serialize_packed ... bench: 37,881 ns/iter (+/- 146) = 8 MB/s test goser::msgpack::bench_decoder ... bench: 50,634 ns/iter (+/- 307) = 5 MB/s test goser::msgpack::bench_encoder ... bench: 25,738 ns/iter (+/- 90) = 11 MB/s test goser::msgpack::bench_populate ... bench: 18,900 ns/iter (+/- 138) test goser::protobuf::bench_decoder ... bench: 2,791 ns/iter (+/- 29) = 102 MB/s test goser::protobuf::bench_encoder ... bench: 75,414 ns/iter (+/- 358) = 3 MB/s test goser::protobuf::bench_populate ... bench: 19,248 ns/iter (+/- 92) test goser::rustc_serialize_json::bench_decoder ... bench: 109,999 ns/iter (+/- 797) = 5 MB/s test goser::rustc_serialize_json::bench_encoder ... bench: 58,777 ns/iter (+/- 418) = 10 MB/s test goser::rustc_serialize_json::bench_populate ... bench: 18,887 ns/iter (+/- 76) test goser::serde_json::bench_deserializer ... bench: 104,803 ns/iter (+/- 770) = 5 MB/s test goser::serde_json::bench_populate ... bench: 18,890 ns/iter (+/- 69) test goser::serde_json::bench_serializer ... bench: 75,046 ns/iter (+/- 435) = 8 MB/s ``` After ``` test goser::bench_clone ... bench: 16,052 ns/iter (+/- 188) = 34 MB/s test goser::bincode::bench_decoder ... bench: 31,194 ns/iter (+/- 941) = 12 MB/s test goser::bincode::bench_deserialize ... bench: 33,934 ns/iter (+/- 352) = 10 MB/s test goser::bincode::bench_encoder ... bench: 30,737 ns/iter (+/- 1,969) = 13 MB/s test goser::bincode::bench_populate ... bench: 17,234 ns/iter (+/- 176) test goser::bincode::bench_serialize ... bench: 28,269 ns/iter (+/- 452) = 12 MB/s test goser::capnp::bench_deserialize ... bench: 2,019 ns/iter (+/- 85) = 221 MB/s test goser::capnp::bench_deserialize_packed ... bench: 10,662 ns/iter (+/- 527) = 31 MB/s test goser::capnp::bench_populate ... bench: 607 ns/iter (+/- 2) test goser::capnp::bench_serialize ... bench: 30,488 ns/iter (+/- 219) = 14 MB/s test goser::capnp::bench_serialize_packed ... bench: 33,731 ns/iter (+/- 201) = 9 MB/s test goser::msgpack::bench_decoder ... bench: 46,921 ns/iter (+/- 461) = 6 MB/s test goser::msgpack::bench_encoder ... bench: 22,315 ns/iter (+/- 96) = 12 MB/s test goser::msgpack::bench_populate ... bench: 17,268 ns/iter (+/- 73) test goser::protobuf::bench_decoder ... bench: 2,658 ns/iter (+/- 44) = 107 MB/s test goser::protobuf::bench_encoder ... bench: 71,024 ns/iter (+/- 359) = 4 MB/s test goser::protobuf::bench_populate ... bench: 17,704 ns/iter (+/- 104) test goser::rustc_serialize_json::bench_decoder ... bench: 107,867 ns/iter (+/- 759) = 5 MB/s test goser::rustc_serialize_json::bench_encoder ... bench: 52,327 ns/iter (+/- 479) = 11 MB/s test goser::rustc_serialize_json::bench_populate ... bench: 17,262 ns/iter (+/- 68) test goser::serde_json::bench_deserializer ... bench: 99,156 ns/iter (+/- 657) = 6 MB/s test goser::serde_json::bench_populate ... bench: 17,264 ns/iter (+/- 77) test goser::serde_json::bench_serializer ... bench: 66,135 ns/iter (+/- 392) = 9 MB/s ``` --- src/librustc_trans/trans/expr.rs | 33 +++++++++++++++++++++++++++++++- src/test/codegen/adjustments.rs | 9 +++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 5b0dae23807a9..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>, diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs index b0438f561b935..d9a7acf112908 100644 --- a/src/test/codegen/adjustments.rs +++ b/src/test/codegen/adjustments.rs @@ -26,3 +26,12 @@ pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] { // 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) +} From 1a3b422207957c1707980d5624f37f9e9d41ce92 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 18 Sep 2015 15:52:19 +0200 Subject: [PATCH 49/61] Use divs with ids rather than as with names. The id attribute has been an official part of HTML since 1997. There is no reason not to use it. --- src/doc/trpl/error-handling.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 230eb0a85ab0f..edb794a54aea4 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -87,7 +87,7 @@ 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; @@ -99,6 +99,7 @@ fn main() { println!("{}", 2 * n); } ``` +
If you give this program zero arguments (error 1) or if the first argument isn't an integer (error 2), the program will panic just like in the first @@ -139,7 +140,7 @@ 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. @@ -152,6 +153,7 @@ fn find(haystack: &str, needle: char) -> Option { None } ``` +
Notice that when this function finds a matching character, it doen't just return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or From 913fe6dbe9425330027b7d75ba16be47d7280d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Fri, 18 Sep 2015 16:30:45 +0200 Subject: [PATCH 50/61] add support for non-standard name of stdc++ library it makes rustc compatible with gcc installation that are using `--program-transform-name' configure flag (on OpenBSD for example). - detects at configure the name of stdc++ library on the system - use the detected name in llvm makefile (with enable-static-stdcpp), and pass it to mklldeps.py - generate mklldeps.rs using this detected name note that CFG_STDCPP_NAME is about stdc++ name, not about libc++. If using libc++, the default name will be `stdc++', but it won't be used when linking. --- configure | 6 ++++++ mk/llvm.mk | 4 ++-- src/etc/mklldeps.py | 5 +++-- 3 files changed, 11 insertions(+), 4 deletions(-) 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/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") From 5104a93a0d9c09bf53921c4d8a2f48a3b7891ffb Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 17 Sep 2015 23:09:28 +0300 Subject: [PATCH 51/61] Revert "Convert negate_unsigned feature gate to a warning" This reverts commit 0ca8e4994ee43ba9dfbded6e129b30ff5fe7a994 and fixes the code to work with current rustc. Fixes #27141 --- src/librustc_lint/builtin.rs | 15 +++++++-------- src/test/bench/shootout-mandelbrot.rs | 2 +- .../feature-gate-negate-unsigned.rs | 10 +++++----- src/test/run-pass/unary-minus-suffix-inference.rs | 2 ++ 4 files changed, 15 insertions(+), 14 deletions(-) rename src/test/{run-pass => compile-fail}/feature-gate-negate-unsigned.rs (67%) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 394bd2abc08c7..5b875e6acbc04 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -49,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; @@ -381,13 +381,12 @@ impl LateLintPass for TypeLimits { 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"); } } } 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/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/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; From 9d3deb4766e1c3c9d0a0f98fc124de7063b47030 Mon Sep 17 00:00:00 2001 From: David Szotten Date: Fri, 18 Sep 2015 17:21:30 +0100 Subject: [PATCH 52/61] fix anchor link --- src/doc/trpl/error-handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index edb794a54aea4..5cd847da823ce 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -210,7 +210,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 From 634ffe562450278e9d77066d3607a1971353979b Mon Sep 17 00:00:00 2001 From: David Szotten Date: Fri, 18 Sep 2015 22:16:31 +0100 Subject: [PATCH 53/61] remove preceeding blank line --- src/doc/trpl/error-handling.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 5cd847da823ce..f7d5db2ddf1d7 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -89,7 +89,6 @@ an integer as an argument, doubles it and prints it.
```rust,should_panic - use std::env; fn main() { From 49b1902345468564a9da16d745cc1a5c5c650908 Mon Sep 17 00:00:00 2001 From: llogiq Date: Sat, 19 Sep 2015 09:04:12 +0200 Subject: [PATCH 54/61] added panic docs for print\! and println\! macros --- src/libstd/macros.rs | 8 ++++++++ 1 file changed, 8 insertions(+) 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 /// /// ``` From 4e42fcd92ad0d918cb0474551601c387fa4999a3 Mon Sep 17 00:00:00 2001 From: David Szotten Date: Sat, 19 Sep 2015 11:43:32 +0100 Subject: [PATCH 55/61] link needs puncuation --- src/doc/trpl/error-handling.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index f7d5db2ddf1d7..6d1d2f4099842 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,7 +41,7 @@ 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) From 30c91cd7f7527cee89e4997827fbe61ea39f2729 Mon Sep 17 00:00:00 2001 From: David Szotten Date: Sat, 19 Sep 2015 11:43:57 +0100 Subject: [PATCH 56/61] angle brackets get mis-parsed. bug? --- src/doc/trpl/error-handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 6d1d2f4099842..9dbc27dfcb8ae 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -45,7 +45,7 @@ systems may want to jump around. * [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) From 3a5e9a3f9934a850753110769c49521a659cd03a Mon Sep 17 00:00:00 2001 From: David Szotten Date: Sat, 19 Sep 2015 11:44:55 +0100 Subject: [PATCH 57/61] wrap more referenced code blocks in divs --- src/doc/trpl/error-handling.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 9dbc27dfcb8ae..521538b955678 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -186,6 +186,7 @@ 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, @@ -202,6 +203,7 @@ impl Option { } } ``` +
The `unwrap` method *abstracts away the case analysis*. This is precisely the thing that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that @@ -251,6 +253,7 @@ 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: +
Indeed, `map` is [defined as a method][2] on `Option` in the standard library. @@ -390,12 +394,14 @@ 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), Err(E), } ``` +
The `Result` type is a richer version of `Option`. Instead of expressing the possibility of *absence* like `Option` does, `Result` expresses the possibility @@ -666,6 +672,7 @@ 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; @@ -682,6 +689,7 @@ fn main() { } } ``` +
There are a couple new things in this example. The first is the use of the [`Option::ok_or`](../std/option/enum.Option.html#method.ok_or) @@ -898,6 +906,7 @@ seen above. Here is a simplified definition of a `try!` macro: +
```rust macro_rules! try { ($e:expr) => (match $e { @@ -906,6 +915,7 @@ macro_rules! try { }); } ``` +
(The [real definition](../std/macro.try!.html) is a bit more sophisticated. We will address that later.) @@ -1158,11 +1168,13 @@ The `std::convert::From` trait is [defined in the standard library](../std/convert/trait.From.html): +
```rust trait From { fn from(T) -> Self; } ``` +
Deliciously simple, yes? `From` is very useful because it gives us a generic way to talk about conversion *from* a particular type `T` to some other type @@ -1238,6 +1250,7 @@ macro_rules! try { This is not it's real definition. It's real definition is [in the standard library](../std/macro.try!.html): +
```rust macro_rules! try { ($e:expr) => (match $e { @@ -1246,6 +1259,7 @@ macro_rules! try { }); } ``` +
There's one tiny but powerful change: the error value is passed through `From::from`. This makes the `try!` macro a lot more powerful because it gives From 436e8d69bf7326181225cb3c0226d11efef5d8f8 Mon Sep 17 00:00:00 2001 From: David Szotten Date: Sat, 19 Sep 2015 11:45:09 +0100 Subject: [PATCH 58/61] its vs it's --- src/doc/trpl/error-handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 521538b955678..4cba68e172462 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -1247,7 +1247,7 @@ 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):
From f7d8b418147fe46f3d0eaba295a0111394446bb0 Mon Sep 17 00:00:00 2001 From: David Szotten Date: Sat, 19 Sep 2015 11:45:30 +0100 Subject: [PATCH 59/61] missing punctuation --- src/doc/trpl/error-handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 4cba68e172462..18d2fae0d7545 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -1470,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`). From 5ab3058569245171a44283fddee6c119a31765b7 Mon Sep 17 00:00:00 2001 From: David Szotten Date: Sat, 19 Sep 2015 12:06:36 +0100 Subject: [PATCH 60/61] change back to anchors; divs break md --- src/doc/trpl/error-handling.md | 36 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 18d2fae0d7545..18ce93ea06a64 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -87,7 +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; @@ -98,7 +99,6 @@ fn main() { println!("{}", 2 * n); } ``` -
If you give this program zero arguments (error 1) or if the first argument isn't an integer (error 2), the program will panic just like in the first @@ -139,7 +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. @@ -152,7 +153,6 @@ fn find(haystack: &str, needle: char) -> Option { None } ``` -
Notice that when this function finds a matching character, it doen't just return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or @@ -186,7 +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, @@ -203,7 +204,6 @@ impl Option { } } ``` -
The `unwrap` method *abstracts away the case analysis*. This is precisely the thing that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that @@ -253,7 +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: - Indeed, `map` is [defined as a method][2] on `Option` in the standard library. @@ -394,14 +394,14 @@ 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), Err(E), } ``` -
The `Result` type is a richer version of `Option`. Instead of expressing the possibility of *absence* like `Option` does, `Result` expresses the possibility @@ -672,7 +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; @@ -689,7 +690,6 @@ fn main() { } } ``` -
There are a couple new things in this example. The first is the use of the [`Option::ok_or`](../std/option/enum.Option.html#method.ok_or) @@ -906,7 +906,8 @@ seen above. Here is a simplified definition of a `try!` macro: -
+ + ```rust macro_rules! try { ($e:expr) => (match $e { @@ -915,7 +916,6 @@ macro_rules! try { }); } ``` -
(The [real definition](../std/macro.try!.html) is a bit more sophisticated. We will address that later.) @@ -1168,13 +1168,13 @@ The `std::convert::From` trait is [defined in the standard library](../std/convert/trait.From.html): -
+ + ```rust trait From { fn from(T) -> Self; } ``` -
Deliciously simple, yes? `From` is very useful because it gives us a generic way to talk about conversion *from* a particular type `T` to some other type @@ -1250,7 +1250,8 @@ macro_rules! try { 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 { @@ -1259,7 +1260,6 @@ macro_rules! try { }); } ``` -
There's one tiny but powerful change: the error value is passed through `From::from`. This makes the `try!` macro a lot more powerful because it gives From a2fbf9da29404c3d1826b2c256440d13541b164f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 19 Sep 2015 08:10:54 -0400 Subject: [PATCH 61/61] Fixed an apparent typo Repertory is a real world, but it doesn't really make sense in that context. --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. #