Auto merge of #33742 - Manishearth:rollup, r=Manishearth

Rollup of 10 pull requests

- Successful merges: #33353, #33611, #33696, #33698, #33705, #33708, #33712, #33720, #33721, #33730
- Failed merges:
This commit is contained in:
bors 2016-05-19 09:45:53 -07:00
commit 764ef92ae7
28 changed files with 221 additions and 80 deletions

View File

@ -12,7 +12,7 @@ the `link_args` attribute. This attribute is applied to `extern` blocks and
specifies raw flags which need to get passed to the linker when producing an specifies raw flags which need to get passed to the linker when producing an
artifact. An example usage would be: artifact. An example usage would be:
``` no_run ```rust,no_run
#![feature(link_args)] #![feature(link_args)]
#[link_args = "-foo -bar -baz"] #[link_args = "-foo -bar -baz"]

View File

@ -319,6 +319,53 @@ assert_eq!(3, answer);
Now we take a trait object, a `&Fn`. And we have to make a reference Now we take a trait object, a `&Fn`. And we have to make a reference
to our closure when we pass it to `call_with_one`, so we use `&||`. to our closure when we pass it to `call_with_one`, so we use `&||`.
A quick note about closures that use explicit lifetimes. Sometimes you might have a closure
that takes a reference like so:
```
fn call_with_ref<F>(some_closure:F) -> i32
where F: Fn(&i32) -> i32 {
let mut value = 0;
some_closure(&value)
}
```
Normally you can specify the lifetime of the parameter to our closure. We
could annotate it on the function declaration:
```ignore
fn call_with_ref<'a, F>(some_closure:F) -> i32
where F: Fn(&'a 32) -> i32 {
```
However this presents a problem with in our case. When you specify the explict
lifetime on a function it binds that lifetime to the *entire* scope of the function
instead of just the invocation scope of our closure. This means that the borrow checker
will see a mutable reference in the same lifetime as our immutable reference and fail
to compile.
In order to say that we only need the lifetime to be valid for the invocation scope
of the closure we can use Higher-Ranked Trait Bounds with the `for<...>` syntax:
```ignore
fn call_with_ref<F>(some_closure:F) -> i32
where F: for<'a> Fn(&'a 32) -> i32 {
```
This lets the Rust compiler find the minimum lifetime to invoke our closure and
satisfy the borrow checker's rules. Our function then compiles and excutes as we
expect.
```
fn call_with_ref<F>(some_closure:F) -> i32
where F: for<'a> Fn(&'a i32) -> i32 {
let mut value = 0;
some_closure(&value)
}
```
# Function pointers and closures # Function pointers and closures
A function pointer is kind of like a closure that has no environment. As such, A function pointer is kind of like a closure that has no environment. As such,
@ -344,7 +391,7 @@ assert_eq!(2, answer);
In this example, we dont strictly need the intermediate variable `f`, In this example, we dont strictly need the intermediate variable `f`,
the name of the function works just fine too: the name of the function works just fine too:
```ignore ```rust,ignore
let answer = call_with_one(&add_one); let answer = call_with_one(&add_one);
``` ```

View File

@ -37,7 +37,7 @@ Let's write a plugin
[`roman_numerals.rs`](https://github.com/rust-lang/rust/tree/master/src/test/auxiliary/roman_numerals.rs) [`roman_numerals.rs`](https://github.com/rust-lang/rust/tree/master/src/test/auxiliary/roman_numerals.rs)
that implements Roman numeral integer literals. that implements Roman numeral integer literals.
```ignore ```rust,ignore
#![crate_type="dylib"] #![crate_type="dylib"]
#![feature(plugin_registrar, rustc_private)] #![feature(plugin_registrar, rustc_private)]
@ -102,7 +102,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
Then we can use `rn!()` like any other macro: Then we can use `rn!()` like any other macro:
```ignore ```rust,ignore
#![feature(plugin)] #![feature(plugin)]
#![plugin(roman_numerals)] #![plugin(roman_numerals)]
@ -132,7 +132,7 @@ Some of the [macro debugging tips](macros.html#debugging-macro-code) are applica
You can use `syntax::parse` to turn token trees into You can use `syntax::parse` to turn token trees into
higher-level syntax elements like expressions: higher-level syntax elements like expressions:
```ignore ```rust,ignore
fn expand_foo(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) fn expand_foo(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
-> Box<MacResult+'static> { -> Box<MacResult+'static> {
@ -169,7 +169,7 @@ infrastructure](../reference.html#lint-check-attributes) with additional checks
code style, safety, etc. Now let's write a plugin [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/auxiliary/lint_plugin_test.rs) code style, safety, etc. Now let's write a plugin [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/auxiliary/lint_plugin_test.rs)
that warns about any item named `lintme`. that warns about any item named `lintme`.
```ignore ```rust,ignore
#![feature(plugin_registrar)] #![feature(plugin_registrar)]
#![feature(box_syntax, rustc_private)] #![feature(box_syntax, rustc_private)]
@ -211,7 +211,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
Then code like Then code like
```ignore ```rust,ignore
#![plugin(lint_plugin_test)] #![plugin(lint_plugin_test)]
fn lintme() { } fn lintme() { }

View File

@ -165,7 +165,7 @@ concurrency bugs.
As an example, here is a Rust program that would have a data race in many As an example, here is a Rust program that would have a data race in many
languages. It will not compile: languages. It will not compile:
```ignore ```rust,ignore
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
@ -204,7 +204,7 @@ Calling `clone()` on an `Rc<T>` will return a new owned reference and bump the
internal reference count. We create one of these for each thread: internal reference count. We create one of these for each thread:
```ignore ```rust,ignore
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std::rc::Rc; use std::rc::Rc;
@ -250,7 +250,7 @@ In essence, `Arc<T>` is a type that lets us share ownership of data _across
threads_. threads_.
```ignore ```rust,ignore
use std::thread; use std::thread;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@ -336,7 +336,7 @@ The lock "release" here is implicit; when the result of the lock (in this case,
Note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of Note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of
[`Mutex`](../std/sync/struct.Mutex.html) has this signature: [`Mutex`](../std/sync/struct.Mutex.html) has this signature:
```ignore ```rust,ignore
fn lock(&self) -> LockResult<MutexGuard<T>> fn lock(&self) -> LockResult<MutexGuard<T>>
``` ```

View File

@ -362,7 +362,7 @@ Heres an example of documenting a macro:
/// # } /// # }
/// ``` /// ```
/// ///
/// ```should_panic /// ```rust,should_panic
/// # #[macro_use] extern crate foo; /// # #[macro_use] extern crate foo;
/// # fn main() { /// # fn main() {
/// panic_unless!(true == false, “Im broken.”); /// panic_unless!(true == false, “Im broken.”);
@ -429,7 +429,7 @@ There are a few more annotations that are useful to help `rustdoc` do the right
thing when testing your code: thing when testing your code:
```rust ```rust
/// ```ignore /// ```rust,ignore
/// fn foo() { /// fn foo() {
/// ``` /// ```
# fn foo() {} # fn foo() {}
@ -441,7 +441,7 @@ with `text` if it's not code, or using `#`s to get a working example that
only shows the part you care about. only shows the part you care about.
```rust ```rust
/// ```should_panic /// ```rust,should_panic
/// assert!(false); /// assert!(false);
/// ``` /// ```
# fn foo() {} # fn foo() {}
@ -451,7 +451,7 @@ only shows the part you care about.
not actually pass as a test. not actually pass as a test.
```rust ```rust
/// ```no_run /// ```rust,no_run
/// loop { /// loop {
/// println!("Hello, world"); /// println!("Hello, world");
/// } /// }
@ -563,7 +563,7 @@ can be useful when changing some options, or when writing a macro.
`rustdoc` will show the documentation for a public re-export in both places: `rustdoc` will show the documentation for a public re-export in both places:
```ignore ```rust,ignore
extern crate foo; extern crate foo;
pub use foo::bar; pub use foo::bar;
@ -575,7 +575,7 @@ documentation in both places.
This behavior can be suppressed with `no_inline`: This behavior can be suppressed with `no_inline`:
```ignore ```rust,ignore
extern crate foo; extern crate foo;
#[doc(no_inline)] #[doc(no_inline)]

View File

@ -28,7 +28,7 @@ and add `extern crate libc;` to your crate root.
The following is a minimal example of calling a foreign function which will The following is a minimal example of calling a foreign function which will
compile if snappy is installed: compile if snappy is installed:
```no_run ```rust,no_run
# #![feature(libc)] # #![feature(libc)]
extern crate libc; extern crate libc;
use libc::size_t; use libc::size_t;
@ -62,7 +62,7 @@ keeping the binding correct at runtime.
The `extern` block can be extended to cover the entire snappy API: The `extern` block can be extended to cover the entire snappy API:
```no_run ```rust,no_run
# #![feature(libc)] # #![feature(libc)]
extern crate libc; extern crate libc;
use libc::{c_int, size_t}; use libc::{c_int, size_t};
@ -209,7 +209,7 @@ A basic example is:
Rust code: Rust code:
```no_run ```rust,no_run
extern fn callback(a: i32) { extern fn callback(a: i32) {
println!("I'm called from C with value {0}", a); println!("I'm called from C with value {0}", a);
} }
@ -262,7 +262,7 @@ referenced Rust object.
Rust code: Rust code:
```no_run ```rust,no_run
#[repr(C)] #[repr(C)]
struct RustObject { struct RustObject {
a: i32, a: i32,
@ -406,7 +406,7 @@ Foreign APIs often export a global variable which could do something like track
global state. In order to access these variables, you declare them in `extern` global state. In order to access these variables, you declare them in `extern`
blocks with the `static` keyword: blocks with the `static` keyword:
```no_run ```rust,no_run
# #![feature(libc)] # #![feature(libc)]
extern crate libc; extern crate libc;
@ -425,7 +425,7 @@ Alternatively, you may need to alter global state provided by a foreign
interface. To do this, statics can be declared with `mut` so we can mutate interface. To do this, statics can be declared with `mut` so we can mutate
them. them.
```no_run ```rust,no_run
# #![feature(libc)] # #![feature(libc)]
extern crate libc; extern crate libc;

View File

@ -134,7 +134,7 @@ x = y = 5
In Rust, however, using `let` to introduce a binding is _not_ an expression. The In Rust, however, using `let` to introduce a binding is _not_ an expression. The
following will produce a compile-time error: following will produce a compile-time error:
```ignore ```rust,ignore
let x = (let y = 5); // expected identifier, found keyword `let` let x = (let y = 5); // expected identifier, found keyword `let`
``` ```
@ -283,7 +283,7 @@ stack backtrace:
A diverging function can be used as any type: A diverging function can be used as any type:
```should_panic ```rust,should_panic
# fn diverges() -> ! { # fn diverges() -> ! {
# panic!("This function never returns!"); # panic!("This function never returns!");
# } # }

View File

@ -4,7 +4,7 @@ For extremely low-level manipulations and performance reasons, one
might wish to control the CPU directly. Rust supports using inline might wish to control the CPU directly. Rust supports using inline
assembly to do this via the `asm!` macro. assembly to do this via the `asm!` macro.
```ignore ```rust,ignore
asm!(assembly template asm!(assembly template
: output operands : output operands
: input operands : input operands

View File

@ -74,7 +74,7 @@ for x in 0..10 {
In slightly more abstract terms, In slightly more abstract terms,
```ignore ```rust,ignore
for var in expression { for var in expression {
code code
} }

View File

@ -78,7 +78,7 @@ macro_rules! vec {
Whoa, thats a lot of new syntax! Lets break it down. Whoa, thats a lot of new syntax! Lets break it down.
```ignore ```rust,ignore
macro_rules! vec { ... } macro_rules! vec { ... }
``` ```
@ -92,7 +92,7 @@ syntax and serves to distinguish a macro from an ordinary function.
The macro is defined through a series of rules, which are pattern-matching The macro is defined through a series of rules, which are pattern-matching
cases. Above, we had cases. Above, we had
```ignore ```rust,ignore
( $( $x:expr ),* ) => { ... }; ( $( $x:expr ),* ) => { ... };
``` ```
@ -112,7 +112,7 @@ separated by commas.
Aside from the special matcher syntax, any Rust tokens that appear in a matcher Aside from the special matcher syntax, any Rust tokens that appear in a matcher
must match exactly. For example, must match exactly. For example,
```rust ```rust,ignore
macro_rules! foo { macro_rules! foo {
(x => $e:expr) => (println!("mode X: {}", $e)); (x => $e:expr) => (println!("mode X: {}", $e));
(y => $e:expr) => (println!("mode Y: {}", $e)); (y => $e:expr) => (println!("mode Y: {}", $e));
@ -147,7 +147,7 @@ The right-hand side of a macro rule is ordinary Rust syntax, for the most part.
But we can splice in bits of syntax captured by the matcher. From the original But we can splice in bits of syntax captured by the matcher. From the original
example: example:
```ignore ```rust,ignore
$( $(
temp_vec.push($x); temp_vec.push($x);
)* )*
@ -165,7 +165,7 @@ within the repeated block.
Another detail: the `vec!` macro has *two* pairs of braces on the right-hand Another detail: the `vec!` macro has *two* pairs of braces on the right-hand
side. They are often combined like so: side. They are often combined like so:
```ignore ```rust,ignore
macro_rules! foo { macro_rules! foo {
() => {{ () => {{
... ...

View File

@ -55,6 +55,8 @@ fn foo(mut x: i32) {
# } # }
``` ```
Note that here, the `x` is mutable, but not the `y`.
[pattern]: patterns.html [pattern]: patterns.html
# Interior vs. Exterior Mutability # Interior vs. Exterior Mutability

View File

@ -123,7 +123,7 @@ fn main() {
For `HasArea` and `Square`, we declare a type parameter `T` and replace For `HasArea` and `Square`, we declare a type parameter `T` and replace
`f64` with it. The `impl` needs more involved modifications: `f64` with it. The `impl` needs more involved modifications:
```ignore ```rust,ignore
impl<T> HasArea<T> for Square<T> impl<T> HasArea<T> for Square<T>
where T: Mul<Output=T> + Copy { ... } where T: Mul<Output=T> + Copy { ... }
``` ```

View File

@ -306,7 +306,7 @@ let y = TraitObject {
Not every trait can be used to make a trait object. For example, vectors implement Not every trait can be used to make a trait object. For example, vectors implement
`Clone`, but if we try to make a trait object: `Clone`, but if we try to make a trait object:
```ignore ```rust,ignore
let v = vec![1, 2, 3]; let v = vec![1, 2, 3];
let o = &v as &Clone; let o = &v as &Clone;
``` ```

View File

@ -195,7 +195,7 @@ fn main() {
`is_square()` needs to check that the sides are equal, so the sides must be of `is_square()` needs to check that the sides are equal, so the sides must be of
a type that implements the [`core::cmp::PartialEq`][PartialEq] trait: a type that implements the [`core::cmp::PartialEq`][PartialEq] trait:
```ignore ```rust,ignore
impl<T: PartialEq> Rectangle<T> { ... } impl<T: PartialEq> Rectangle<T> { ... }
``` ```

View File

@ -40,7 +40,7 @@ The indices count from `0`, so the third element is `v[2]`.
Its also important to note that you must index with the `usize` type: Its also important to note that you must index with the `usize` type:
```ignore ```rust,ignore
let v = vec![1, 2, 3, 4, 5]; let v = vec![1, 2, 3, 4, 5];
let i: usize = 0; let i: usize = 0;
@ -71,7 +71,7 @@ you cannot index with an `i32`.
If you try to access an index that doesnt exist: If you try to access an index that doesnt exist:
```ignore ```rust,ignore
let v = vec![1, 2, 3]; let v = vec![1, 2, 3];
println!("Item 7 is {}", v[7]); println!("Item 7 is {}", v[7]);
``` ```

@ -1 +1 @@
Subproject commit 6598e2cbfd7e09bfca249cc3dcbf889735f73ce1 Subproject commit b19b5465a1235be3323363cdc11838739b593029

View File

@ -502,6 +502,33 @@ fn foo(a: &mut i32) {
``` ```
"##, "##,
E0502: r##"
This error indicates that you are trying to borrow a variable as mutable when it
has already been borrowed as immutable.
Example of erroneous code:
```compile_fail
fn bar(x: &mut i32) {}
fn foo(a: &mut i32) {
let ref y = a; // a is borrowed as immutable.
bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed
// as immutable
}
```
To fix this error, ensure that you don't have any other references to the
variable before trying to access it mutably:
```
fn bar(x: &mut i32) {}
fn foo(a: &mut i32) {
bar(a);
let ref y = a; // ok!
}
```
For more information on the rust ownership system, take a look at
https://doc.rust-lang.org/stable/book/references-and-borrowing.html.
"##,
E0504: r##" E0504: r##"
This error occurs when an attempt is made to move a borrowed variable into a This error occurs when an attempt is made to move a borrowed variable into a
closure. closure.
@ -984,7 +1011,6 @@ fn main() {
register_diagnostics! { register_diagnostics! {
E0385, // {} in an aliasable location E0385, // {} in an aliasable location
E0388, // {} in a static location E0388, // {} in a static location
E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
E0503, // cannot use `..` because it was mutably borrowed E0503, // cannot use `..` because it was mutably borrowed
E0508, // cannot move out of type `..`, a non-copy fixed-size array E0508, // cannot move out of type `..`, a non-copy fixed-size array
E0524, // two closures require unique access to `..` at the same time E0524, // two closures require unique access to `..` at the same time

View File

@ -215,15 +215,18 @@ fn report_elision_failure(
{ {
let mut m = String::new(); let mut m = String::new();
let len = params.len(); let len = params.len();
let mut any_lifetimes = false;
for (i, info) in params.into_iter().enumerate() { let elided_params: Vec<_> = params.into_iter()
.filter(|info| info.lifetime_count > 0)
.collect();
let elided_len = elided_params.len();
for (i, info) in elided_params.into_iter().enumerate() {
let ElisionFailureInfo { let ElisionFailureInfo {
name, lifetime_count: n, have_bound_regions name, lifetime_count: n, have_bound_regions
} = info; } = info;
any_lifetimes = any_lifetimes || (n > 0);
let help_name = if name.is_empty() { let help_name = if name.is_empty() {
format!("argument {}", i + 1) format!("argument {}", i + 1)
} else { } else {
@ -237,13 +240,14 @@ fn report_elision_failure(
if have_bound_regions { "free " } else { "" } ) if have_bound_regions { "free " } else { "" } )
})[..]); })[..]);
if len == 2 && i == 0 { if elided_len == 2 && i == 0 {
m.push_str(" or "); m.push_str(" or ");
} else if i + 2 == len { } else if i + 2 == elided_len {
m.push_str(", or "); m.push_str(", or ");
} else if i + 1 != len { } else if i != elided_len - 1 {
m.push_str(", "); m.push_str(", ");
} }
} }
if len == 0 { if len == 0 {
@ -252,7 +256,7 @@ fn report_elision_failure(
there is no value for it to be borrowed from"); there is no value for it to be borrowed from");
help!(db, help!(db,
"consider giving it a 'static lifetime"); "consider giving it a 'static lifetime");
} else if !any_lifetimes { } else if elided_len == 0 {
help!(db, help!(db,
"this function's return type contains a borrowed value with \ "this function's return type contains a borrowed value with \
an elided lifetime, but the lifetime cannot be derived from \ an elided lifetime, but the lifetime cannot be derived from \
@ -260,7 +264,7 @@ fn report_elision_failure(
help!(db, help!(db,
"consider giving it an explicit bounded or 'static \ "consider giving it an explicit bounded or 'static \
lifetime"); lifetime");
} else if len == 1 { } else if elided_len == 1 {
help!(db, help!(db,
"this function's return type contains a borrowed value, but \ "this function's return type contains a borrowed value, but \
the signature does not say which {} it is borrowed from", the signature does not say which {} it is borrowed from",

View File

@ -1566,7 +1566,8 @@ impl<'a> fmt::Display for Item<'a> {
write!(fmt, "</span>")?; // in-band write!(fmt, "</span>")?; // in-band
write!(fmt, "<span class='out-of-band'>")?; write!(fmt, "<span class='out-of-band'>")?;
if let Some(version) = self.item.stable_since() { if let Some(version) = self.item.stable_since() {
write!(fmt, "<span class='since'>{}</span>", version)?; write!(fmt, "<span class='since' title='Stable since Rust version {0}'>{0}</span>",
version)?;
} }
write!(fmt, write!(fmt,
r##"<span id='render-detail'> r##"<span id='render-detail'>
@ -2136,7 +2137,7 @@ fn render_stability_since_raw<'a>(w: &mut fmt::Formatter,
containing_ver: Option<&'a str>) -> fmt::Result { containing_ver: Option<&'a str>) -> fmt::Result {
if let Some(v) = ver { if let Some(v) = ver {
if containing_ver != ver && v.len() > 0 { if containing_ver != ver && v.len() > 0 {
write!(w, "<div class=\"since\">{}</div>", write!(w, "<div class='since' title='Stable since Rust version {0}'>{0}</div>",
v)? v)?
} }
} }

View File

@ -423,7 +423,7 @@ impl EmitterWriter {
&format!(" (defined in {})", &format!(" (defined in {})",
self.cm.span_to_filename(def_site_span))); self.cm.span_to_filename(def_site_span)));
} }
let snippet = self.cm.span_to_string(sp); let snippet = self.cm.span_to_string(trace.call_site);
print_diagnostic(&mut self.dst, &snippet, Note, &diag_string, None)?; print_diagnostic(&mut self.dst, &snippet, Note, &diag_string, None)?;
} }
Ok(()) Ok(())

View File

@ -70,15 +70,9 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
// Keep going, outside-in. // Keep going, outside-in.
let fully_expanded = fld.fold_expr(expanded_expr); let fully_expanded = fld.fold_expr(expanded_expr);
let span = fld.new_span(span);
fld.cx.bt_pop(); fld.cx.bt_pop();
fully_expanded.map(|e| ast::Expr { fully_expanded
id: ast::DUMMY_NODE_ID,
node: e.node,
span: span,
attrs: e.attrs,
})
} }
ast::ExprKind::InPlace(placer, value_expr) => { ast::ExprKind::InPlace(placer, value_expr) => {

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// error-pattern: borrowed value does not live long enough
struct defer<'a> { struct defer<'a> {
x: &'a [&'a str], x: &'a [&'a str],
} }
@ -28,6 +30,5 @@ fn defer<'r>(x: &'r [&'r str]) -> defer<'r> {
fn main() { fn main() {
let x = defer(&vec!("Goodbye", "world!")); let x = defer(&vec!("Goodbye", "world!"));
//~^ ERROR borrowed value does not live long enough
x.x[0]; x.x[0];
} }

View File

@ -11,22 +11,26 @@
// macro f should not be able to inject a reference to 'n'. // macro f should not be able to inject a reference to 'n'.
macro_rules! f { () => (n) } macro_rules! f { () => (n) }
//~^ ERROR unresolved name `n`
//~| ERROR unresolved name `n`
//~| ERROR unresolved name `n`
//~| ERROR unresolved name `n`
fn main() -> (){ fn main() -> (){
for n in 0..1 { for n in 0..1 {
println!("{}", f!()); //~ ERROR unresolved name `n` println!("{}", f!());
} }
if let Some(n) = None { if let Some(n) = None {
println!("{}", f!()); //~ ERROR unresolved name `n` println!("{}", f!());
} }
if false { if false {
} else if let Some(n) = None { } else if let Some(n) = None {
println!("{}", f!()); //~ ERROR unresolved name `n` println!("{}", f!());
} }
while let Some(n) = None { while let Some(n) = None {
println!("{}", f!()); //~ ERROR unresolved name `n` println!("{}", f!());
} }
} }

View File

@ -0,0 +1,35 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// Test that lifetime elision error messages correctly omit parameters
// with no elided lifetimes
struct S<'a> {
field: &'a i32,
}
fn f(a: &S, b: i32) -> &i32 {
//~^ ERROR missing lifetime specifier [E0106]
//~^^ HELP does not say which one of `a`'s 2 elided lifetimes it is borrowed from
panic!();
}
fn g(a: &S, b: bool, c: &i32) -> &i32 {
//~^ ERROR missing lifetime specifier [E0106]
//~^^ HELP does not say whether it is borrowed from one of `a`'s 2 elided lifetimes or `c`
panic!();
}
fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
//~^ ERROR missing lifetime specifier [E0106]
//~^^ HELP does not say whether it is borrowed from `a`, one of `c`'s 2 elided lifetimes, or `d`
panic!();
}

View File

@ -36,13 +36,13 @@ macro_rules! fake_method_expr {
macro_rules! fake_field_expr { macro_rules! fake_field_expr {
() => { () => {
1.fake 1.fake //~ ERROR no field with that name
} }
} }
macro_rules! fake_anon_field_expr { macro_rules! fake_anon_field_expr {
() => { () => {
(1).0 (1).0 //~ ERROR type was not a tuple
} }
} }
@ -52,8 +52,6 @@ fn main() {
fake_anon_field_stmt!(); //~ NOTE in this expansion of fake_anon_field_stmt!(); //~ NOTE in this expansion of
let _ = fake_method_expr!(); //~ NOTE in this expansion of let _ = fake_method_expr!(); //~ NOTE in this expansion of
let _ = fake_field_expr!(); //~ ERROR no field with that name let _ = fake_field_expr!(); //~ NOTE in this expansion of
//~^ NOTE in this expansion of let _ = fake_anon_field_expr!(); //~ NOTE in this expansion of
let _ = fake_anon_field_expr!(); //~ ERROR type was not a tuple
//~^ NOTE in this expansion of
} }

View File

@ -12,20 +12,19 @@
// we replace the span of the expanded expression with that of the call site. // we replace the span of the expanded expression with that of the call site.
macro_rules! nested_expr { macro_rules! nested_expr {
() => (fake) () => (fake) //~ ERROR unresolved name
//~^ ERROR unresolved name
} }
macro_rules! call_nested_expr { macro_rules! call_nested_expr {
() => (nested_expr!()) () => (nested_expr!()) //~ NOTE in this expansion of nested_expr!
} }
macro_rules! call_nested_expr_sum { macro_rules! call_nested_expr_sum {
() => { 1 + nested_expr!(); } //~ ERROR unresolved name () => { 1 + nested_expr!(); } //~ NOTE in this expansion of nested_expr!
//~^ NOTE in this expansion of nested_expr!
} }
fn main() { fn main() {
1 + call_nested_expr!(); //~ ERROR unresolved name 1 + call_nested_expr!(); //~ NOTE in this expansion of call_nested_expr!
//~^ NOTE in this expansion of call_nested_expr!
call_nested_expr_sum!(); //~ NOTE in this expansion of call_nested_expr_sum!(); //~ NOTE in this expansion of
} }

View File

@ -21,11 +21,11 @@ macro_rules! myprint {
} }
macro_rules! myprintln { macro_rules! myprintln {
($fmt:expr) => (myprint!(concat!($fmt, "\n"))); //~ ERROR invalid reference to argument `0` ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); //~ NOTE in this expansion of myprint!
//~^ NOTE in this expansion of myprint! //~^ NOTE in this expansion of concat!
//~^^ NOTE in this expansion of concat!
} }
fn main() { fn main() {
myprintln!("{}"); //~ NOTE in this expansion of myprintln!("{}"); //~ ERROR invalid reference to argument `0`
//~^ NOTE in this expansion of
} }

View File

@ -0,0 +1,30 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test error message when enum variants are used as types
// issue 21225
enum Ty {
A,
B(Ty::A),
//~^ ERROR: found value `Ty::A` used as a type
}
// issue 19197
enum E {
A
}
impl E::A {}
//~^ ERROR: found value `E::A` used as a type
fn main() {}