Auto merge of #28516 - steveklabnik:rollup, r=steveklabnik
- Successful merges: #28400, #28430, #28443, #28483, #28485, #28496, #28511, #28515 - Failed merges:
This commit is contained in:
commit
837840c61f
16 changed files with 192 additions and 83 deletions
|
@ -1,6 +1,6 @@
|
||||||
# Compiler Test Documentation
|
# 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:
|
comments to test the Rust compiler. There are two groups of commands:
|
||||||
|
|
||||||
1. Header commands
|
1. Header commands
|
||||||
|
@ -29,11 +29,11 @@ The error levels that you can have are:
|
||||||
3. `NOTE`
|
3. `NOTE`
|
||||||
4. `HELP` and `SUGGESTION`*
|
4. `HELP` and `SUGGESTION`*
|
||||||
|
|
||||||
\* **Note**: `SUGGESTION` must follow emediatly after `HELP`.
|
\* **Note**: `SUGGESTION` must follow immediately after `HELP`.
|
||||||
|
|
||||||
## Summary of Header Commands
|
## 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.
|
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
|
* `ignore-X` where `X` is an architecture, OS or stage will ignore the test accordingly
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#
|
#
|
||||||
# * check - Run the complete test suite
|
# * 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
|
# command if you want to build Rust again, after an update
|
||||||
# of the git repository.
|
# of the git repository.
|
||||||
#
|
#
|
||||||
|
|
|
@ -28,7 +28,7 @@ systems may want to jump around.
|
||||||
* [The `Result` type](#the-result-type)
|
* [The `Result` type](#the-result-type)
|
||||||
* [Parsing integers](#parsing-integers)
|
* [Parsing integers](#parsing-integers)
|
||||||
* [The `Result` type alias idiom](#the-result-type-alias-idiom)
|
* [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)
|
* [Working with multiple error types](#working-with-multiple-error-types)
|
||||||
* [Composing `Option` and `Result`](#composing-option-and-result)
|
* [Composing `Option` and `Result`](#composing-option-and-result)
|
||||||
* [The limits of combinators](#the-limits-of-combinators)
|
* [The limits of combinators](#the-limits-of-combinators)
|
||||||
|
@ -41,11 +41,11 @@ systems may want to jump around.
|
||||||
* [The real `try!` macro](#the-real-try!-macro)
|
* [The real `try!` macro](#the-real-try!-macro)
|
||||||
* [Composing custom error types](#composing-custom-error-types)
|
* [Composing custom error types](#composing-custom-error-types)
|
||||||
* [Advice for library writers](#advice-for-library-writers)
|
* [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)
|
* [Initial setup](#initial-setup)
|
||||||
* [Argument parsing](#argument-parsing)
|
* [Argument parsing](#argument-parsing)
|
||||||
* [Writing the logic](#writing-the-logic)
|
* [Writing the logic](#writing-the-logic)
|
||||||
* [Error handling with `Box<Error>`](#error-handling-with-box<error>)
|
* [Error handling with `Box<Error>`](#error-handling-with-box%3Cerror%3E)
|
||||||
* [Reading from stdin](#reading-from-stdin)
|
* [Reading from stdin](#reading-from-stdin)
|
||||||
* [Error handling with a custom type](#error-handling-with-a-custom-type)
|
* [Error handling with a custom type](#error-handling-with-a-custom-type)
|
||||||
* [Adding functionality](#adding-functionality)
|
* [Adding functionality](#adding-functionality)
|
||||||
|
@ -87,9 +87,9 @@ thread '<main>' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5
|
||||||
Here's another example that is slightly less contrived. A program that accepts
|
Here's another example that is slightly less contrived. A program that accepts
|
||||||
an integer as an argument, doubles it and prints it.
|
an integer as an argument, doubles it and prints it.
|
||||||
|
|
||||||
<div id="code-unwrap-double">
|
<a name="code-unwrap-double"></a>
|
||||||
```rust,should_panic
|
|
||||||
|
|
||||||
|
```rust,should_panic
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -99,7 +99,6 @@ fn main() {
|
||||||
println!("{}", 2 * n);
|
println!("{}", 2 * n);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</div>
|
|
||||||
|
|
||||||
If you give this program zero arguments (error 1) or if the first argument
|
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
|
isn't an integer (error 2), the program will panic just like in the first
|
||||||
|
@ -140,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
|
programmer to handle that absence. Let's take a look at an example that tries
|
||||||
to find a character in a string:
|
to find a character in a string:
|
||||||
|
|
||||||
<div id="code-option-ex-string-find">
|
<a name="code-option-ex-string-find"></a>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// Searches `haystack` for the Unicode character `needle`. If one is found, the
|
// Searches `haystack` for the Unicode character `needle`. If one is found, the
|
||||||
// byte offset of the character is returned. Otherwise, `None` is returned.
|
// byte offset of the character is returned. Otherwise, `None` is returned.
|
||||||
|
@ -153,7 +153,6 @@ fn find(haystack: &str, needle: char) -> Option<usize> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</div>
|
|
||||||
|
|
||||||
Notice that when this function finds a matching character, it doen't just
|
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
|
return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or
|
||||||
|
@ -187,6 +186,8 @@ But wait, what about `unwrap` used in [`unwrap-double`](#code-unwrap-double)?
|
||||||
There was no case analysis there! Instead, the case analysis was put inside the
|
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:
|
`unwrap` method for you. You could define it yourself if you want:
|
||||||
|
|
||||||
|
<a name="code-option-def-unwrap"></a>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
enum Option<T> {
|
enum Option<T> {
|
||||||
None,
|
None,
|
||||||
|
@ -210,7 +211,7 @@ that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that
|
||||||
|
|
||||||
### Composing `Option<T>` values
|
### Composing `Option<T>` 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,
|
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
|
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
|
no extension. This *possibility of absence* is encoded into the types using
|
||||||
|
@ -252,6 +253,8 @@ option is `None`, in which case, just return `None`.
|
||||||
Rust has parametric polymorphism, so it is very easy to define a combinator
|
Rust has parametric polymorphism, so it is very easy to define a combinator
|
||||||
that abstracts this pattern:
|
that abstracts this pattern:
|
||||||
|
|
||||||
|
<a name="code-option-map"></a>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A {
|
fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A {
|
||||||
match option {
|
match option {
|
||||||
|
@ -391,6 +394,8 @@ remove choices because they will panic if `Option<T>` is `None`.
|
||||||
The `Result` type is also
|
The `Result` type is also
|
||||||
[defined in the standard library][6]:
|
[defined in the standard library][6]:
|
||||||
|
|
||||||
|
<a name="code-result-def-1"></a>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
enum Result<T, E> {
|
enum Result<T, E> {
|
||||||
Ok(T),
|
Ok(T),
|
||||||
|
@ -667,6 +672,8 @@ with both an `Option` and a `Result`, the solution is *usually* to convert the
|
||||||
(from `env::args()`) means the user didn't invoke the program correctly. We
|
(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:
|
could just use a `String` to describe the error. Let's try:
|
||||||
|
|
||||||
|
<a name="code-error-double-string"></a>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
@ -899,6 +906,8 @@ seen above.
|
||||||
|
|
||||||
Here is a simplified definition of a `try!` macro:
|
Here is a simplified definition of a `try!` macro:
|
||||||
|
|
||||||
|
<a nama name="code-try-def-simple"></a>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
macro_rules! try {
|
macro_rules! try {
|
||||||
($e:expr) => (match $e {
|
($e:expr) => (match $e {
|
||||||
|
@ -1159,6 +1168,8 @@ The `std::convert::From` trait is
|
||||||
[defined in the standard
|
[defined in the standard
|
||||||
library](../std/convert/trait.From.html):
|
library](../std/convert/trait.From.html):
|
||||||
|
|
||||||
|
<a name="code-from-def"></a>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
trait From<T> {
|
trait From<T> {
|
||||||
fn from(T) -> Self;
|
fn from(T) -> Self;
|
||||||
|
@ -1236,9 +1247,11 @@ macro_rules! try {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This is not it's real definition. It's real definition is
|
This is not its real definition. Its real definition is
|
||||||
[in the standard library](../std/macro.try!.html):
|
[in the standard library](../std/macro.try!.html):
|
||||||
|
|
||||||
|
<a name="code-try-def"></a>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
macro_rules! try {
|
macro_rules! try {
|
||||||
($e:expr) => (match $e {
|
($e:expr) => (match $e {
|
||||||
|
@ -1457,7 +1470,7 @@ representation. But certainly, this will vary depending on use cases.
|
||||||
At a minimum, you should probably implement the
|
At a minimum, you should probably implement the
|
||||||
[`Error`](../std/error/trait.Error.html)
|
[`Error`](../std/error/trait.Error.html)
|
||||||
trait. This will give users of your library some minimum flexibility for
|
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
|
means that users are guaranteed the ability to obtain a string representation
|
||||||
of an error (because it requires impls for both `fmt::Debug` and
|
of an error (because it requires impls for both `fmt::Debug` and
|
||||||
`fmt::Display`).
|
`fmt::Display`).
|
||||||
|
|
|
@ -147,7 +147,7 @@ a few tricks up their sleeves.
|
||||||
|
|
||||||
For example, they’re [immutable][immutable] by default. That’s why our example
|
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
|
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
|
‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough
|
||||||
to use for now:
|
to use for now:
|
||||||
|
|
||||||
|
|
|
@ -464,40 +464,36 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
match (new_loan.kind, old_loan.kind) {
|
match (new_loan.kind, old_loan.kind) {
|
||||||
(ty::MutBorrow, ty::MutBorrow) => {
|
(ty::MutBorrow, ty::MutBorrow) => {
|
||||||
self.bccx.span_err(
|
span_err!(self.bccx, new_loan.span, E0499,
|
||||||
new_loan.span,
|
"cannot borrow `{}`{} as mutable \
|
||||||
&format!("cannot borrow `{}`{} as mutable \
|
|
||||||
more than once at a time",
|
more than once at a time",
|
||||||
nl, new_loan_msg))
|
nl, new_loan_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
(ty::UniqueImmBorrow, _) => {
|
(ty::UniqueImmBorrow, _) => {
|
||||||
self.bccx.span_err(
|
span_err!(self.bccx, new_loan.span, E0500,
|
||||||
new_loan.span,
|
"closure requires unique access to `{}` \
|
||||||
&format!("closure requires unique access to `{}` \
|
|
||||||
but {} is already borrowed{}",
|
but {} is already borrowed{}",
|
||||||
nl, ol_pronoun, old_loan_msg));
|
nl, ol_pronoun, old_loan_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, ty::UniqueImmBorrow) => {
|
(_, ty::UniqueImmBorrow) => {
|
||||||
self.bccx.span_err(
|
span_err!(self.bccx, new_loan.span, E0501,
|
||||||
new_loan.span,
|
"cannot borrow `{}`{} as {} because \
|
||||||
&format!("cannot borrow `{}`{} as {} because \
|
|
||||||
previous closure requires unique access",
|
previous closure requires unique access",
|
||||||
nl, new_loan_msg, new_loan.kind.to_user_str()));
|
nl, new_loan_msg, new_loan.kind.to_user_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
self.bccx.span_err(
|
span_err!(self.bccx, new_loan.span, E0502,
|
||||||
new_loan.span,
|
"cannot borrow `{}`{} as {} because \
|
||||||
&format!("cannot borrow `{}`{} as {} because \
|
|
||||||
{} is also borrowed as {}{}",
|
{} is also borrowed as {}{}",
|
||||||
nl,
|
nl,
|
||||||
new_loan_msg,
|
new_loan_msg,
|
||||||
new_loan.kind.to_user_str(),
|
new_loan.kind.to_user_str(),
|
||||||
ol_pronoun,
|
ol_pronoun,
|
||||||
old_loan.kind.to_user_str(),
|
old_loan.kind.to_user_str(),
|
||||||
old_loan_msg));
|
old_loan_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,11 +613,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) {
|
match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) {
|
||||||
UseOk => { }
|
UseOk => { }
|
||||||
UseWhileBorrowed(loan_path, loan_span) => {
|
UseWhileBorrowed(loan_path, loan_span) => {
|
||||||
self.bccx.span_err(
|
span_err!(self.bccx, span, E0503,
|
||||||
span,
|
"cannot use `{}` because it was mutably borrowed",
|
||||||
&format!("cannot use `{}` because it was mutably borrowed",
|
&self.bccx.loan_path_to_string(copy_path));
|
||||||
&self.bccx.loan_path_to_string(copy_path))
|
|
||||||
);
|
|
||||||
self.bccx.span_note(
|
self.bccx.span_note(
|
||||||
loan_span,
|
loan_span,
|
||||||
&format!("borrow of `{}` occurs here",
|
&format!("borrow of `{}` occurs here",
|
||||||
|
@ -642,18 +636,19 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
match self.analyze_restrictions_on_use(id, move_path, ty::MutBorrow) {
|
match self.analyze_restrictions_on_use(id, move_path, ty::MutBorrow) {
|
||||||
UseOk => { }
|
UseOk => { }
|
||||||
UseWhileBorrowed(loan_path, loan_span) => {
|
UseWhileBorrowed(loan_path, loan_span) => {
|
||||||
let err_message = match move_kind {
|
match move_kind {
|
||||||
move_data::Captured =>
|
move_data::Captured =>
|
||||||
format!("cannot move `{}` into closure because it is borrowed",
|
span_err!(self.bccx, span, E0504,
|
||||||
|
"cannot move `{}` into closure because it is borrowed",
|
||||||
&self.bccx.loan_path_to_string(move_path)),
|
&self.bccx.loan_path_to_string(move_path)),
|
||||||
move_data::Declared |
|
move_data::Declared |
|
||||||
move_data::MoveExpr |
|
move_data::MoveExpr |
|
||||||
move_data::MovePat =>
|
move_data::MovePat =>
|
||||||
format!("cannot move out of `{}` because it is borrowed",
|
span_err!(self.bccx, span, E0505,
|
||||||
|
"cannot move out of `{}` because it is borrowed",
|
||||||
&self.bccx.loan_path_to_string(move_path))
|
&self.bccx.loan_path_to_string(move_path))
|
||||||
};
|
};
|
||||||
|
|
||||||
self.bccx.span_err(span, &err_message[..]);
|
|
||||||
self.bccx.span_note(
|
self.bccx.span_note(
|
||||||
loan_span,
|
loan_span,
|
||||||
&format!("borrow of `{}` occurs here",
|
&format!("borrow of `{}` occurs here",
|
||||||
|
@ -820,10 +815,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
loan_path: &LoanPath<'tcx>,
|
loan_path: &LoanPath<'tcx>,
|
||||||
loan: &Loan) {
|
loan: &Loan) {
|
||||||
self.bccx.span_err(
|
span_err!(self.bccx, span, E0506,
|
||||||
span,
|
"cannot assign to `{}` because it is borrowed",
|
||||||
&format!("cannot assign to `{}` because it is borrowed",
|
self.bccx.loan_path_to_string(loan_path));
|
||||||
self.bccx.loan_path_to_string(loan_path)));
|
|
||||||
self.bccx.span_note(
|
self.bccx.span_note(
|
||||||
loan.span,
|
loan.span,
|
||||||
&format!("borrow of `{}` occurs here",
|
&format!("borrow of `{}` occurs here",
|
||||||
|
|
|
@ -119,18 +119,18 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
mc::cat_deref(_, _, mc::Implicit(..)) |
|
mc::cat_deref(_, _, mc::Implicit(..)) |
|
||||||
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
|
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
|
||||||
mc::cat_static_item => {
|
mc::cat_static_item => {
|
||||||
bccx.span_err(move_from.span,
|
span_err!(bccx, move_from.span, E0507,
|
||||||
&format!("cannot move out of {}",
|
"cannot move out of {}",
|
||||||
move_from.descriptive_string(bccx.tcx)));
|
move_from.descriptive_string(bccx.tcx));
|
||||||
}
|
}
|
||||||
|
|
||||||
mc::cat_interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
|
mc::cat_interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
|
||||||
let expr = bccx.tcx.map.expect_expr(move_from.id);
|
let expr = bccx.tcx.map.expect_expr(move_from.id);
|
||||||
if let hir::ExprIndex(..) = expr.node {
|
if let hir::ExprIndex(..) = expr.node {
|
||||||
bccx.span_err(move_from.span,
|
span_err!(bccx, move_from.span, E0508,
|
||||||
&format!("cannot move out of type `{}`, \
|
"cannot move out of type `{}`, \
|
||||||
a non-copy fixed-size array",
|
a non-copy fixed-size array",
|
||||||
b.ty));
|
b.ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,11 +139,10 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
match b.ty.sty {
|
match b.ty.sty {
|
||||||
ty::TyStruct(def, _) |
|
ty::TyStruct(def, _) |
|
||||||
ty::TyEnum(def, _) if def.has_dtor() => {
|
ty::TyEnum(def, _) if def.has_dtor() => {
|
||||||
bccx.span_err(
|
span_err!(bccx, move_from.span, E0509,
|
||||||
move_from.span,
|
"cannot move out of type `{}`, \
|
||||||
&format!("cannot move out of type `{}`, \
|
|
||||||
which defines the `Drop` trait",
|
which defines the `Drop` trait",
|
||||||
b.ty));
|
b.ty);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
bccx.span_bug(move_from.span, "this path should not cause illegal move")
|
bccx.span_bug(move_from.span, "this path should not cause illegal move")
|
||||||
|
|
|
@ -803,6 +803,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||||
self.tcx.sess.span_err(s, m);
|
self.tcx.sess.span_err(s, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn span_err_with_code(&self, s: Span, msg: &str, code: &str) {
|
||||||
|
self.tcx.sess.span_err_with_code(s, msg, code);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn span_bug(&self, s: Span, m: &str) {
|
pub fn span_bug(&self, s: Span, m: &str) {
|
||||||
self.tcx.sess.span_bug(s, m);
|
self.tcx.sess.span_bug(s, m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,12 +263,50 @@ fn mutable() {
|
||||||
You can read more about cell types in the API documentation:
|
You can read more about cell types in the API documentation:
|
||||||
|
|
||||||
https://doc.rust-lang.org/std/cell/
|
https://doc.rust-lang.org/std/cell/
|
||||||
"##
|
"##,
|
||||||
|
|
||||||
|
E0499: r##"
|
||||||
|
A variable was borrowed as mutable more than once. Erroneous code example:
|
||||||
|
|
||||||
|
```
|
||||||
|
let mut i = 0;
|
||||||
|
let mut x = &mut i;
|
||||||
|
let mut a = &mut i;
|
||||||
|
// error: cannot borrow `i` as mutable more than once at a time
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that in rust, you can either have many immutable references, or one
|
||||||
|
mutable reference. Take a look at
|
||||||
|
https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more
|
||||||
|
information. Example:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
let mut i = 0;
|
||||||
|
let mut x = &mut i; // ok!
|
||||||
|
|
||||||
|
// or:
|
||||||
|
let mut i = 0;
|
||||||
|
let a = &i; // ok!
|
||||||
|
let b = &i; // still ok!
|
||||||
|
let c = &i; // still ok!
|
||||||
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
register_diagnostics! {
|
register_diagnostics! {
|
||||||
E0385, // {} in an aliasable location
|
E0385, // {} in an aliasable location
|
||||||
E0388, // {} in a static location
|
E0388, // {} in a static location
|
||||||
E0389 // {} in a `&` reference
|
E0389, // {} in a `&` reference
|
||||||
|
E0500, // closure requires unique access to `..` but .. is already borrowed
|
||||||
|
E0501, // cannot borrow `..`.. as .. because previous closure requires unique access
|
||||||
|
E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
|
||||||
|
E0503, // cannot use `..` because it was mutably borrowed
|
||||||
|
E0504, // cannot move `..` into closure because it is borrowed
|
||||||
|
E0505, // cannot move out of `..` because it is borrowed
|
||||||
|
E0506, // cannot assign to `..` because it is borrowed
|
||||||
|
E0507, // cannot move out of ..
|
||||||
|
E0508, // cannot move out of type `..`, a non-copy fixed-size array
|
||||||
|
E0509, // cannot move out of type `..`, which defines the `Drop` trait
|
||||||
}
|
}
|
||||||
|
|
|
@ -542,7 +542,11 @@ fn link_binary_output(sess: &Session,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir");
|
let tmpdir = match TempDir::new("rustc") {
|
||||||
|
Ok(tmpdir) => tmpdir,
|
||||||
|
Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
|
||||||
|
};
|
||||||
|
|
||||||
match crate_type {
|
match crate_type {
|
||||||
config::CrateTypeRlib => {
|
config::CrateTypeRlib => {
|
||||||
link_rlib(sess, Some(trans), &objects, &out_filename,
|
link_rlib(sess, Some(trans), &objects, &out_filename,
|
||||||
|
|
21
src/librustc_trans/diagnostics.rs
Normal file
21
src/librustc_trans/diagnostics.rs
Normal file
|
@ -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 <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.
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
register_long_diagnostics! {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
register_diagnostics! {
|
||||||
|
E0510, // invalid use of `return_address` intrinsic: function does not use out pointer
|
||||||
|
E0511, // invalid monomorphization of `{}` intrinsic
|
||||||
|
E0512, // transmute called on types with potentially different sizes...
|
||||||
|
}
|
|
@ -80,6 +80,8 @@ pub mod back {
|
||||||
pub mod msvc;
|
pub mod msvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod diagnostics;
|
||||||
|
|
||||||
pub mod trans;
|
pub mod trans;
|
||||||
pub mod save;
|
pub mod save;
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,9 @@ use syntax::ast;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
|
||||||
|
use rustc::session::Session;
|
||||||
|
use syntax::codemap::Span;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
pub fn get_simple_intrinsic(ccx: &CrateContext, item: &hir::ForeignItem) -> Option<ValueRef> {
|
pub fn get_simple_intrinsic(ccx: &CrateContext, item: &hir::ForeignItem) -> Option<ValueRef> {
|
||||||
|
@ -99,6 +102,10 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &hir::ForeignItem) -> Opti
|
||||||
Some(ccx.get_intrinsic(&name))
|
Some(ccx.get_intrinsic(&name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn span_transmute_size_error(a: &Session, b: Span, msg: &str) {
|
||||||
|
span_err!(a, b, E0512, "{}", msg);
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs late verification that intrinsics are used correctly. At present,
|
/// Performs late verification that intrinsics are used correctly. At present,
|
||||||
/// the only intrinsic that needs such verification is `transmute`.
|
/// the only intrinsic that needs such verification is `transmute`.
|
||||||
pub fn check_intrinsics(ccx: &CrateContext) {
|
pub fn check_intrinsics(ccx: &CrateContext) {
|
||||||
|
@ -127,8 +134,7 @@ pub fn check_intrinsics(ccx: &CrateContext) {
|
||||||
last_failing_id = Some(transmute_restriction.id);
|
last_failing_id = Some(transmute_restriction.id);
|
||||||
|
|
||||||
if transmute_restriction.original_from != transmute_restriction.substituted_from {
|
if transmute_restriction.original_from != transmute_restriction.substituted_from {
|
||||||
ccx.sess().span_err(
|
span_transmute_size_error(ccx.sess(), transmute_restriction.span,
|
||||||
transmute_restriction.span,
|
|
||||||
&format!("transmute called on types with potentially different sizes: \
|
&format!("transmute called on types with potentially different sizes: \
|
||||||
{} (could be {} bit{}) to {} (could be {} bit{})",
|
{} (could be {} bit{}) to {} (could be {} bit{})",
|
||||||
transmute_restriction.original_from,
|
transmute_restriction.original_from,
|
||||||
|
@ -138,8 +144,7 @@ pub fn check_intrinsics(ccx: &CrateContext) {
|
||||||
to_type_size as usize,
|
to_type_size as usize,
|
||||||
if to_type_size == 1 {""} else {"s"}));
|
if to_type_size == 1 {""} else {"s"}));
|
||||||
} else {
|
} else {
|
||||||
ccx.sess().span_err(
|
span_transmute_size_error(ccx.sess(), transmute_restriction.span,
|
||||||
transmute_restriction.span,
|
|
||||||
&format!("transmute called on types with different sizes: \
|
&format!("transmute called on types with different sizes: \
|
||||||
{} ({} bit{}) to {} ({} bit{})",
|
{} ({} bit{}) to {} ({} bit{})",
|
||||||
transmute_restriction.original_from,
|
transmute_restriction.original_from,
|
||||||
|
@ -798,7 +803,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||||
|
|
||||||
(_, "return_address") => {
|
(_, "return_address") => {
|
||||||
if !fcx.caller_expects_out_pointer {
|
if !fcx.caller_expects_out_pointer {
|
||||||
tcx.sess.span_err(call_info.span,
|
span_err!(tcx.sess, call_info.span, E0510,
|
||||||
"invalid use of `return_address` intrinsic: function \
|
"invalid use of `return_address` intrinsic: function \
|
||||||
does not use out pointer");
|
does not use out pointer");
|
||||||
C_null(Type::i8p(ccx))
|
C_null(Type::i8p(ccx))
|
||||||
|
@ -1439,6 +1444,10 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
|
||||||
return rust_try
|
return rust_try
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
|
||||||
|
span_err!(a, b, E0511, "{}", c);
|
||||||
|
}
|
||||||
|
|
||||||
fn generic_simd_intrinsic<'blk, 'tcx, 'a>
|
fn generic_simd_intrinsic<'blk, 'tcx, 'a>
|
||||||
(bcx: Block<'blk, 'tcx>,
|
(bcx: Block<'blk, 'tcx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -1457,7 +1466,8 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
|
||||||
emit_error!($msg, )
|
emit_error!($msg, )
|
||||||
};
|
};
|
||||||
($msg: tt, $($fmt: tt)*) => {
|
($msg: tt, $($fmt: tt)*) => {
|
||||||
bcx.sess().span_err(call_info.span,
|
span_invalid_monomorphization_error(
|
||||||
|
bcx.sess(), call_info.span,
|
||||||
&format!(concat!("invalid monomorphization of `{}` intrinsic: ",
|
&format!(concat!("invalid monomorphization of `{}` intrinsic: ",
|
||||||
$msg),
|
$msg),
|
||||||
name, $($fmt)*));
|
name, $($fmt)*));
|
||||||
|
|
|
@ -54,7 +54,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function browserSupportsHistoryApi() {
|
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) {
|
function highlightSourceLines(ev) {
|
||||||
|
|
|
@ -68,6 +68,10 @@ macro_rules! panic {
|
||||||
/// necessary to use `io::stdout().flush()` to ensure the output is emitted
|
/// necessary to use `io::stdout().flush()` to ensure the output is emitted
|
||||||
/// immediately.
|
/// immediately.
|
||||||
///
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if writing to `io::stdout()` fails.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -99,6 +103,10 @@ macro_rules! print {
|
||||||
/// Use the `format!` syntax to write data to the standard output.
|
/// Use the `format!` syntax to write data to the standard output.
|
||||||
/// See `std::fmt` for more information.
|
/// See `std::fmt` for more information.
|
||||||
///
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if writing to `io::stdout()` fails.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
4
src/test/run-make/issue-14698/Makefile
Normal file
4
src/test/run-make/issue-14698/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
-include ../tools.mk
|
||||||
|
|
||||||
|
all:
|
||||||
|
TMP=fake TMPDIR=fake $(RUSTC) foo.rs 2>&1 | grep "couldn't create a temp dir:"
|
11
src/test/run-make/issue-14698/foo.rs
Normal file
11
src/test/run-make/issue-14698/foo.rs
Normal file
|
@ -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 <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.
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in a new issue