Auto merge of #25888 - steveklabnik:rollup, r=steveklabnik
- Successful merges: #25788, #25861, #25864, #25865, #25866, #25873, #25876, #25883, #25886 - Failed merges:
This commit is contained in:
commit
b77d60adb0
@ -20,6 +20,7 @@ for any operation that is clearly associated with a particular
|
||||
type.
|
||||
|
||||
Methods have numerous advantages over functions:
|
||||
|
||||
* They do not need to be imported or qualified to be used: all you
|
||||
need is a value of the appropriate type.
|
||||
* Their invocation performs autoborrowing (including mutable borrows).
|
||||
|
@ -159,7 +159,7 @@ fn foo(a: u8) { ... }
|
||||
Note that
|
||||
[`ascii::Ascii`](http://static.rust-lang.org/doc/master/std/ascii/struct.Ascii.html)
|
||||
is a _wrapper_ around `u8` that guarantees the highest bit is zero; see
|
||||
[newtype patterns]() for more details on creating typesafe wrappers.
|
||||
[newtype patterns](../types/newtype.md) for more details on creating typesafe wrappers.
|
||||
|
||||
Static enforcement usually comes at little run-time cost: it pushes the
|
||||
costs to the boundaries (e.g. when a `u8` is first converted into an
|
||||
|
@ -34,7 +34,7 @@ Prefer
|
||||
|
||||
```rust
|
||||
let foo = match bar {
|
||||
Baz => 0,
|
||||
Baz => 0,
|
||||
Quux => 1
|
||||
};
|
||||
```
|
||||
@ -44,7 +44,7 @@ over
|
||||
```rust
|
||||
let foo;
|
||||
match bar {
|
||||
Baz => {
|
||||
Baz => {
|
||||
foo = 0;
|
||||
}
|
||||
Quux => {
|
||||
@ -61,8 +61,8 @@ conditional expression.
|
||||
Prefer
|
||||
|
||||
```rust
|
||||
s.iter().map(|x| x * 2)
|
||||
.collect::<Vec<_>>()
|
||||
let v = s.iter().map(|x| x * 2)
|
||||
.collect::<Vec<_>>();
|
||||
```
|
||||
|
||||
over
|
||||
|
@ -16,7 +16,7 @@ If `T` is such a data structure, consider introducing a `T` _builder_:
|
||||
value. When possible, choose a better name: e.g. `Command` is the builder for
|
||||
`Process`.
|
||||
2. The builder constructor should take as parameters only the data _required_ to
|
||||
to make a `T`.
|
||||
make a `T`.
|
||||
3. The builder should offer a suite of convenient methods for configuration,
|
||||
including setting up compound inputs (like slices) incrementally.
|
||||
These methods should return `self` to allow chaining.
|
||||
|
@ -15,7 +15,7 @@ language would.
|
||||
|
||||
[rust]: http://rust-lang.org
|
||||
|
||||
“The Rust Programming Language” is split into seven sections. This introduction
|
||||
“The Rust Programming Language” is split into eight sections. This introduction
|
||||
is the first. After this:
|
||||
|
||||
* [Getting started][gs] - Set up your computer for Rust development.
|
||||
|
@ -19,7 +19,7 @@ In the example above `x` and `y` have arity 2. `z` has arity 3.
|
||||
|
||||
When a compiler is compiling your program, it does a number of different
|
||||
things. One of the things that it does is turn the text of your program into an
|
||||
‘abstract syntax tree’, or‘AST’. This tree is a representation of the
|
||||
‘abstract syntax tree’, or ‘AST’. This tree is a representation of the
|
||||
structure of your program. For example, `2 + 3` can be turned into a tree:
|
||||
|
||||
```text
|
||||
|
@ -134,8 +134,29 @@ x: &'a i32,
|
||||
# }
|
||||
```
|
||||
|
||||
uses it. So why do we need a lifetime here? We need to ensure that any
|
||||
reference to the contained `i32` does not outlive the containing `Foo`.
|
||||
uses it. So why do we need a lifetime here? We need to ensure that any reference
|
||||
to a `Foo` cannot outlive the reference to an `i32` it contains.
|
||||
|
||||
If you have multiple references, you can use the same lifetime multiple times:
|
||||
|
||||
```rust
|
||||
fn x_or_y<'a>(x: &'a str, y: &'a str) -> &'a str {
|
||||
# x
|
||||
# }
|
||||
```
|
||||
|
||||
This says that `x` and `y` both are alive for the same scope, and that the
|
||||
return value is also alive for that scope. If you wanted `x` and `y` to have
|
||||
different lifetimes, you can use multiple lifetime parameters:
|
||||
|
||||
```rust
|
||||
fn x_or_y<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
|
||||
# x
|
||||
# }
|
||||
```
|
||||
|
||||
In this example, `x` and `y` have different valid scopes, but the return value
|
||||
has the same lifetime as `x`.
|
||||
|
||||
## Thinking in scopes
|
||||
|
||||
|
@ -4,7 +4,7 @@ Functions are great, but if you want to call a bunch of them on some data, it
|
||||
can be awkward. Consider this code:
|
||||
|
||||
```rust,ignore
|
||||
baz(bar(foo)));
|
||||
baz(bar(foo));
|
||||
```
|
||||
|
||||
We would read this left-to right, and so we see ‘baz bar foo’. But this isn’t the
|
||||
|
@ -285,7 +285,7 @@ fn bar<T, K>(x: T, y: K) where T: Clone, K: Clone + Debug {
|
||||
|
||||
fn main() {
|
||||
foo("Hello", "world");
|
||||
bar("Hello", "workd");
|
||||
bar("Hello", "world");
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -52,20 +52,61 @@ pub use intrinsics::transmute;
|
||||
/// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally)
|
||||
/// * Panicking destructors are likely to leak local resources
|
||||
///
|
||||
/// # When To Use
|
||||
///
|
||||
/// There's only a few reasons to use this function. They mainly come
|
||||
/// up in unsafe code or FFI code.
|
||||
///
|
||||
/// * You have an uninitialized value, perhaps for performance reasons, and
|
||||
/// need to prevent the destructor from running on it.
|
||||
/// * You have two copies of a value (like `std::mem::swap`), but need the
|
||||
/// destructor to only run once to prevent a double free.
|
||||
/// * Transferring resources across FFI boundries.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Leak some heap memory by never deallocating it.
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let heap_memory = Box::new(3);
|
||||
/// mem::forget(heap_memory);
|
||||
/// ```
|
||||
///
|
||||
/// Leak an I/O object, never closing the file.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use std::mem;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// // Leak some heap memory by never deallocating it
|
||||
/// let heap_memory = Box::new(3);
|
||||
/// mem::forget(heap_memory);
|
||||
///
|
||||
/// // Leak an I/O object, never closing the file
|
||||
/// let file = File::open("foo.txt").unwrap();
|
||||
/// mem::forget(file);
|
||||
/// ```
|
||||
///
|
||||
/// The swap function uses forget to good effect.
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem;
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// fn swap<T>(x: &mut T, y: &mut T) {
|
||||
/// unsafe {
|
||||
/// // Give ourselves some scratch space to work with
|
||||
/// let mut t: T = mem::uninitialized();
|
||||
///
|
||||
/// // Perform the swap, `&mut` pointers never alias
|
||||
/// ptr::copy_nonoverlapping(&*x, &mut t, 1);
|
||||
/// ptr::copy_nonoverlapping(&*y, x, 1);
|
||||
/// ptr::copy_nonoverlapping(&t, y, 1);
|
||||
///
|
||||
/// // y and t now point to the same thing, but we need to completely
|
||||
/// // forget `t` because we do not want to run the destructor for `T`
|
||||
/// // on its value, which is still owned somewhere outside this function.
|
||||
/// mem::forget(t);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn forget<T>(t: T) {
|
||||
unsafe { intrinsics::forget(t) }
|
||||
@ -267,8 +308,9 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
||||
ptr::copy_nonoverlapping(&*y, x, 1);
|
||||
ptr::copy_nonoverlapping(&t, y, 1);
|
||||
|
||||
// y and t now point to the same thing, but we need to completely forget `t`
|
||||
// because it's no longer relevant.
|
||||
// y and t now point to the same thing, but we need to completely
|
||||
// forget `t` because we do not want to run the destructor for `T`
|
||||
// on its value, which is still owned somewhere outside this function.
|
||||
forget(t);
|
||||
}
|
||||
}
|
||||
|
@ -196,9 +196,13 @@ const Y: i32 = A;
|
||||
"##,
|
||||
|
||||
E0015: r##"
|
||||
The only function calls allowed in static or constant expressions are enum
|
||||
variant constructors or struct constructors (for unit or tuple structs). This
|
||||
is because Rust currently does not support compile-time function execution.
|
||||
The only functions that can be called in static or constant expressions are
|
||||
`const` functions. Rust currently does not support more general compile-time
|
||||
function execution.
|
||||
|
||||
See [RFC 911] for more details on the design of `const fn`s.
|
||||
|
||||
[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
|
||||
"##,
|
||||
|
||||
E0018: r##"
|
||||
@ -842,6 +846,53 @@ struct Foo<T: 'static> {
|
||||
foo: &'static T
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0378: r##"
|
||||
Method calls that aren't calls to inherent `const` methods are disallowed
|
||||
in statics, constants, and constant functions.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
|
||||
|
||||
struct Foo(i32);
|
||||
|
||||
impl Foo {
|
||||
const fn foo(&self) -> i32 {
|
||||
self.bar() // error, `bar` isn't `const`
|
||||
}
|
||||
|
||||
fn bar(&self) -> i32 { self.0 }
|
||||
}
|
||||
```
|
||||
|
||||
For more information about `const fn`'s, see [RFC 911].
|
||||
|
||||
[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
|
||||
"##,
|
||||
|
||||
E0394: r##"
|
||||
From [RFC 246]:
|
||||
|
||||
> It is illegal for a static to reference another static by value. It is
|
||||
> required that all references be borrowed.
|
||||
|
||||
[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
|
||||
"##,
|
||||
|
||||
E0397: r##"
|
||||
It is not allowed for a mutable static to allocate or have destructors. For
|
||||
example:
|
||||
|
||||
```
|
||||
// error: mutable statics are not allowed to have boxes
|
||||
static mut FOO: Option<Box<usize>> = None;
|
||||
|
||||
// error: mutable statics are not allowed to have destructors
|
||||
static mut BAR: Option<Vec<i32>> = None;
|
||||
```
|
||||
"##
|
||||
|
||||
}
|
||||
@ -891,9 +942,6 @@ register_diagnostics! {
|
||||
E0315, // cannot invoke closure outside of its lifetime
|
||||
E0316, // nested quantification of lifetimes
|
||||
E0370, // discriminant overflow
|
||||
E0378, // method calls limited to constant inherent methods
|
||||
E0394, // cannot refer to other statics by value, use the address-of
|
||||
// operator or a constant instead
|
||||
E0395, // pointer comparison in const-expr
|
||||
E0396 // pointer dereference in const-expr
|
||||
}
|
||||
|
@ -273,13 +273,13 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
|
||||
let suffix = if tcontents.has_dtor() {
|
||||
"destructors"
|
||||
} else if tcontents.owns_owned() {
|
||||
"owned pointers"
|
||||
"boxes"
|
||||
} else {
|
||||
return
|
||||
};
|
||||
|
||||
self.tcx.sess.span_err(e.span, &format!("mutable statics are not allowed \
|
||||
to have {}", suffix));
|
||||
span_err!(self.tcx.sess, e.span, E0397,
|
||||
"mutable statics are not allowed to have {}", suffix);
|
||||
}
|
||||
|
||||
fn check_static_type(&self, e: &ast::Expr) {
|
||||
|
@ -170,6 +170,31 @@ Reference:
|
||||
http://doc.rust-lang.org/reference.html#trait-objects
|
||||
"##,
|
||||
|
||||
E0040: r##"
|
||||
It is not allowed to manually call destructors in Rust. It is also not
|
||||
necessary to do this since `drop` is called automatically whenever a value goes
|
||||
out of scope.
|
||||
|
||||
Here's an example of this error:
|
||||
|
||||
```
|
||||
struct Foo {
|
||||
x: i32,
|
||||
}
|
||||
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("kaboom");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = Foo { x: -7 };
|
||||
x.drop(); // error: explicit use of destructor method
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0046: r##"
|
||||
When trying to make some type implement a trait `Foo`, you must, at minimum,
|
||||
provide implementations for all of `Foo`'s required methods (meaning the
|
||||
@ -241,7 +266,7 @@ impl Foo for Bar {
|
||||
fn foo(x: i16) { }
|
||||
|
||||
// error, values differ in mutability
|
||||
fn foo(&mut self) { }
|
||||
fn bar(&mut self) { }
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@ -542,6 +567,21 @@ enum Empty {}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0087: r##"
|
||||
Too many type parameters were supplied for a function. For example:
|
||||
|
||||
```
|
||||
fn foo<T>() {}
|
||||
|
||||
fn main() {
|
||||
foo::<f64, bool>(); // error, expected 1 parameter, found 2 parameters
|
||||
}
|
||||
```
|
||||
|
||||
The number of supplied parameters much exactly match the number of defined type
|
||||
parameters.
|
||||
"##,
|
||||
|
||||
E0089: r##"
|
||||
Not enough type parameters were supplied for a function. For example:
|
||||
|
||||
@ -1098,6 +1138,13 @@ Trait2 { ... }`) does not work if the trait is not object-safe. Please see the
|
||||
[RFC 255]: https://github.com/rust-lang/rfcs/pull/255
|
||||
"##,
|
||||
|
||||
E0379: r##"
|
||||
Trait methods cannot be declared `const` by design. For more information, see
|
||||
[RFC 911].
|
||||
|
||||
[RFC 911]: https://github.com/rust-lang/rfcs/pull/911
|
||||
"##,
|
||||
|
||||
E0380: r##"
|
||||
Default impls are only allowed for traits with no methods or associated items.
|
||||
For more information see the [opt-in builtin traits RFC](https://github.com/rust
|
||||
@ -1113,7 +1160,6 @@ register_diagnostics! {
|
||||
E0034, // multiple applicable methods in scope
|
||||
E0035, // does not take type parameters
|
||||
E0036, // incorrect number of type parameters given for this method
|
||||
E0040, // explicit use of destructor method
|
||||
E0044, // foreign items may not have type parameters
|
||||
E0045, // variadic function must have C calling convention
|
||||
E0057, // method has an incompatible type for trait
|
||||
@ -1128,7 +1174,6 @@ register_diagnostics! {
|
||||
E0077,
|
||||
E0085,
|
||||
E0086,
|
||||
E0087,
|
||||
E0088,
|
||||
E0090,
|
||||
E0091,
|
||||
@ -1235,7 +1280,6 @@ register_diagnostics! {
|
||||
// between structures
|
||||
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
|
||||
// between structures with the same definition
|
||||
E0379, // trait fns cannot be const
|
||||
E0390, // only a single inherent implementation marked with
|
||||
// `#[lang = \"{}\"]` is allowed for the `{}` primitive
|
||||
E0391, // unsupported cyclic reference between types/traits detected
|
||||
|
@ -12,6 +12,6 @@
|
||||
|
||||
static mut a: Box<isize> = box 3;
|
||||
//~^ ERROR allocations are not allowed in statics
|
||||
//~^^ ERROR mutable statics are not allowed to have owned pointers
|
||||
//~^^ ERROR mutable statics are not allowed to have boxes
|
||||
|
||||
fn main() {}
|
||||
|
@ -17,14 +17,12 @@
|
||||
|
||||
use std::slice;
|
||||
|
||||
pub type IoResult<T> = Result<T, ()>;
|
||||
|
||||
trait MyWriter {
|
||||
fn my_write(&mut self, buf: &[u8]) -> IoResult<()>;
|
||||
fn my_write(&mut self, buf: &[u8]) -> Result<(), ()>;
|
||||
}
|
||||
|
||||
impl<'a> MyWriter for &'a mut [u8] {
|
||||
fn my_write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
fn my_write(&mut self, buf: &[u8]) -> Result<(), ()> {
|
||||
slice::bytes::copy_memory(buf, *self);
|
||||
|
||||
let write_len = buf.len();
|
||||
|
Loading…
Reference in New Issue
Block a user