diff --git a/src/doc/style/features/functions-and-methods/README.md b/src/doc/style/features/functions-and-methods/README.md index 2dcfc382d0b..611cd564cca 100644 --- a/src/doc/style/features/functions-and-methods/README.md +++ b/src/doc/style/features/functions-and-methods/README.md @@ -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). diff --git a/src/doc/style/features/functions-and-methods/input.md b/src/doc/style/features/functions-and-methods/input.md index a1310de2e60..072021194c1 100644 --- a/src/doc/style/features/functions-and-methods/input.md +++ b/src/doc/style/features/functions-and-methods/input.md @@ -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 diff --git a/src/doc/style/features/let.md b/src/doc/style/features/let.md index f13a84f6fee..01dff3dccea 100644 --- a/src/doc/style/features/let.md +++ b/src/doc/style/features/let.md @@ -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::>() +let v = s.iter().map(|x| x * 2) + .collect::>(); ``` over diff --git a/src/doc/style/ownership/builders.md b/src/doc/style/ownership/builders.md index 54992341ce5..348be516e37 100644 --- a/src/doc/style/ownership/builders.md +++ b/src/doc/style/ownership/builders.md @@ -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. diff --git a/src/doc/trpl/README.md b/src/doc/trpl/README.md index d7f810dd857..12384b00b43 100644 --- a/src/doc/trpl/README.md +++ b/src/doc/trpl/README.md @@ -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. diff --git a/src/doc/trpl/glossary.md b/src/doc/trpl/glossary.md index 9845fcbdcd1..c97da0e95b8 100644 --- a/src/doc/trpl/glossary.md +++ b/src/doc/trpl/glossary.md @@ -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 diff --git a/src/doc/trpl/lifetimes.md b/src/doc/trpl/lifetimes.md index 04ae4c7ccf3..580960b7e80 100644 --- a/src/doc/trpl/lifetimes.md +++ b/src/doc/trpl/lifetimes.md @@ -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 diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index e5f490e15e1..1f694f71a88 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -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 diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index 9ac170ddec2..2ef9e7ca22e 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -285,7 +285,7 @@ fn bar(x: T, y: K) where T: Clone, K: Clone + Debug { fn main() { foo("Hello", "world"); - bar("Hello", "workd"); + bar("Hello", "world"); } ``` diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7749d053285..26c6e899df1 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -52,20 +52,61 @@ /// * `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(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) { unsafe { intrinsics::forget(t) } @@ -267,8 +308,9 @@ pub fn swap(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); } } diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index a1fa1834ef4..a3577981c1e 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -196,9 +196,13 @@ struct X { x: (), } "##, 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 { 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> = None; + +// error: mutable statics are not allowed to have destructors +static mut BAR: Option> = None; +``` "## } @@ -891,9 +942,6 @@ struct Foo { 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 } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index ff7c570284f..7403462df8a 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -273,13 +273,13 @@ fn check_static_mut_type(&self, e: &ast::Expr) { 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) { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index edfad77d588..c822a7faa19 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -170,6 +170,31 @@ struct Dog { 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() {} + +fn main() { + foo::(); // 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 @@ impl Baz for Bar { } // Note: This is OK [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 @@ impl Baz for Bar { } // Note: This is OK 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 @@ impl Baz for Bar { } // Note: This is OK E0077, E0085, E0086, - E0087, E0088, E0090, E0091, @@ -1235,7 +1280,6 @@ impl Baz for Bar { } // Note: This is OK // 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 diff --git a/src/test/compile-fail/static-mut-not-constant.rs b/src/test/compile-fail/static-mut-not-constant.rs index 08148328edc..e3bb01e6970 100644 --- a/src/test/compile-fail/static-mut-not-constant.rs +++ b/src/test/compile-fail/static-mut-not-constant.rs @@ -12,6 +12,6 @@ static mut a: Box = 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() {} diff --git a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs index 5eecf27db67..5b104d4bb0c 100644 --- a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs +++ b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs @@ -17,14 +17,12 @@ use std::slice; -pub type IoResult = Result; - 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();