From 047aac5cc60016b7c7f2a92f335b4a82b07ec59c Mon Sep 17 00:00:00 2001 From: iirelu Date: Mon, 3 Sep 2018 16:25:51 +0200 Subject: [PATCH 01/54] Flesh out struct keyword docs The whole keyword docs thing is pretty new in Rust's history and needs some work before it's a shining gem. Here's hoping I can provide that. I basically shoved in a bunch of the most important information from the reference and the book, along with leaving links to both at the end. I don't think keyword docs need to have complete detail, just all the broad strokes, so if someone's confused about a usage of a keyword they can look at the std documentation for that keyword. --- src/libstd/keyword_docs.rs | 104 ++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 8 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index d70cf132b3c3a..b5593e44f8b5b 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -59,21 +59,109 @@ mod let_keyword { } #[doc(keyword = "struct")] // -/// The `struct` keyword. +/// The keyword used to define structs. /// -/// The `struct` keyword is used to define a struct type. +/// Structs in Rust come in three flavours: Regular structs, tuple structs, +/// and empty structs. /// -/// Example: +/// ```rust +/// struct Regular { +/// field1: f32, +/// field2: String, +/// pub field3: bool +/// } /// +/// struct Tuple(u32, String); +/// +/// struct Empty; /// ``` -/// struct Foo { -/// field1: u32, -/// field2: String, +/// +/// Regular structs are the most commonly used. Each field defined within them has a name and a +/// type, and once defined can be accessed using `example_struct.field` syntax. The fields of a +/// struct share its mutability, so `foo.bar = 2;` would only be valid if `foo` was mutable. Adding +/// `pub` to a field makes it visible to code in other modules, as well as allowing it to be +/// directly accessed and modified. +/// +/// Tuple structs are similar to regular structs, but its fields have no names. They are used like +/// tuples, with deconstruction possible via `let TupleStruct(x, y) = foo;` syntax. For accessing +/// individual variables, the same syntax is used as with regular tuples, namely `foo.0`, `foo.1`, +/// etc, starting at zero. +/// +/// Empty structs, or unit-like structs, are most commonly used as markers, for example +/// [`PhantomData`]. Empty structs have a size of zero bytes, but unlike empty enums they can be +/// instantiated, making them similar to the unit type `()`. Unit-like structs are useful when you +/// need to implement a trait on something, but don't need to store any data inside it. +/// +/// # Instantiation +/// +/// Structs can be instantiated in a manner of different ways, each of which can be mixed and +/// matched as needed. The most common way to make a new struct is via a constructor method such as +/// `new()`, but when that isn't available (or you're writing the constructor itself), struct +/// literal syntax is used: +/// +/// ```rust +/// # struct Foo { field1: f32, field2: String, etc: bool } +/// let example = Foo { +/// field1: 42.0, +/// field2: "blah".to_string(), +/// etc: true, +/// }; +/// ``` +/// +/// It's only possible to directly instantiate a struct using struct literal syntax when all of its +/// fields are visible to you. +/// +/// There are a handful of shortcuts provided to make writing constructors more convenient, most +/// common of which is the Field Init shorthand. When there is a variable and a field of the same +/// name, the assignment can be simplified from `field: field` into simply `field`. The following +/// example of a hypothetical constructor demonstrates this: +/// +/// ```rust +/// struct User { +/// name: String, +/// admin: bool, +/// } +/// +/// impl User { +/// pub fn new(name: String) -> Self { +/// Self { +/// name, +/// admin: false, +/// } +/// } /// } /// ``` /// -/// There are different kinds of structs. For more information, take a look at the -/// [Rust Book][book]. +/// Another shortcut for struct instantiation is available when you need to make a new struct that +/// shares most of a previous struct's values called struct update syntax: +/// +/// ```rust +/// # struct Foo { field1: String, field2: () } +/// # let thing = Foo { field1: "".to_string(), field2: () }; +/// let updated_thing = Foo { +/// field1: "a new value".to_string(), +/// ..thing +/// }; +/// ``` /// +/// Tuple structs are instantiated in the same way as tuples themselves, except with the struct's +/// name as a prefix: `Foo(123, false, 0.1)`. +/// +/// Empty structs are instantiated with just their name and nothing else. `let thing = +/// EmptyStruct;` +/// +/// +/// # Style conventions +/// +/// Structs are always written in CamelCase, with few exceptions. While the trailing comma on a +/// struct's list of fields can be omitted, it's usually kept for convenience in adding and +/// removing fields down the line. +/// +/// For more information on structs, take a look at the [Rust Book][book] or the +/// [Reference][reference]. +/// +/// [`PhantomData`]: marker/struct.PhantomData.html /// [book]: https://doc.rust-lang.org/book/second-edition/ch05-01-defining-structs.html +/// [reference]: https://doc.rust-lang.org/reference/items/structs.html + mod struct_keyword { } From 1142bbdfc4e9ae48045e9b7a2c6b507aa0626e84 Mon Sep 17 00:00:00 2001 From: iirelu Date: Mon, 3 Sep 2018 19:41:01 +0200 Subject: [PATCH 02/54] Add docs for `as` keyword It's pretty basic and could do with more details, but it's a good starter until someone else improves it. --- src/libstd/keyword_docs.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index b5593e44f8b5b..db447c1b363d1 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -8,6 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[doc(keyword = "as")] +// +/// The type coercion keyword +/// +/// `as` is most commonly used to turn primitive types into other primitive types, but it has other +/// uses that include turning pointers into addresses, addresses into pointers, and pointers into +/// other pointers. +/// +/// ```rust +/// let thing1: u8 = 89.0 as u8; +/// assert_eq!('B' as u32, 66); +/// assert_eq!(thing1 as char, 'Y'); +/// let thing2: f32 = thing1 as f32 + 10.5; +/// assert_eq!(true as u8 + thing2 as u8, 100); +/// ``` +/// +/// In general, any coercion that can be performed via writing out type hints can also be done +/// using `as`, so instead of writing `let x: u32 = 123`, you can write `let x = 123 as u32` (Note: +/// `let x = 123u32` would be best in that situation). The same is not true in the other direction, +/// however, explicitly using `as` allows a few more coercions that aren't allowed implicitly, such +/// as changing the type of a raw pointer or turning closures into raw pointers. +/// +/// For more information on what `as` is capable of, see the [Reference] +/// +/// [Reference]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions +mod as_keyword { } + #[doc(keyword = "fn")] // /// The `fn` keyword. From c1bd8a9c615b6ec9124c9525c8d0898c806b62c8 Mon Sep 17 00:00:00 2001 From: iirelu Date: Mon, 3 Sep 2018 20:23:53 +0200 Subject: [PATCH 03/54] Add keyword docs on const Turns out writing docs on keywords that are used in multiple different places in entirely different contexts gets a little harder. I put a footnote on `*const` syntax just to make sure you can find it if need be, but it might need more detail. --- src/libstd/keyword_docs.rs | 57 +++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index db447c1b363d1..5c3a2b18e1cba 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -10,7 +10,7 @@ #[doc(keyword = "as")] // -/// The type coercion keyword +/// The type coercion keyword. /// /// `as` is most commonly used to turn primitive types into other primitive types, but it has other /// uses that include turning pointers into addresses, addresses into pointers, and pointers into @@ -35,6 +35,61 @@ /// [Reference]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions mod as_keyword { } +#[doc(keyword = "const")] +// +/// The keyword for defining constants. +/// +/// Sometimes a certain value is used many times throughout a program, and it can become +/// inconvenient to copy it over and over. What's more, it's not always possible or desirable to +/// make it a variable that gets carried around to each function that needs it. In these cases, the +/// `const` keyword provides a convenient alternative to code duplication. +/// +/// ```rust +/// const THING: u32 = 0xABAD1DEA; +/// +/// let foo = 123 + THING; +/// ``` +/// +/// Constants must be explicitly typed, unlike with `let` you can't ignore its type and let the +/// compiler figure it out. Any constant value can be defined in a const, which in practice happens +/// to be most things that would be reasonable to have a constant. For example, you can't have a +/// File as a const. +/// +/// The only lifetime allowed in a constant is 'static, which is the lifetime that encompasses all +/// others in a Rust program. For example, if you wanted to define a constant string, it would look +/// like this: +/// +/// ```rust +/// const WORDS: &'static str = "hello rust!"; +/// ``` +/// +/// Thanks to static lifetime elision, you usually don't have to explicitly use 'static: +/// +/// ```rust +/// const WORDS: &str = "hello convenience!"; +/// ``` +/// +/// `const` items looks remarkably similar to [`static`] items, which introduces some confusion as +/// to which one should be used at which times. To put it simply, constants are inlined wherever +/// they're used, making using them identical to simply replacing the name of the const with its +/// value. Static variables on the other hand point to a single location in memory, which all +/// accesses share. This means that, unlike with constants, they can't have destructors, but it +/// also means that (via unsafe code) they can be mutable, which is useful for the rare situations +/// in which you can't avoid using global state. +/// +/// Constants, as with statics, should always be in SCREAMING_SNAKE_CASE. +/// +/// The `const` keyword is also used in raw pointers in combination with `mut`, as seen in `*const +/// T` and `*mut T`. More about that can be read at the [pointer] primitive part of the Rust docs. +/// +/// For more detail on `const`, see the [Rust Book] or the [Reference] +/// +/// [`static`]: keyword.static.html +/// [pointer]: primitive.pointer.html +/// [Rust Book]: https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants +/// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html +mod const_keyword { } + #[doc(keyword = "fn")] // /// The `fn` keyword. From 6cbcfa276185d650ca04fb96ddec15f1b82c5806 Mon Sep 17 00:00:00 2001 From: iirelu Date: Mon, 3 Sep 2018 21:56:30 +0200 Subject: [PATCH 04/54] Fix a few small things, re-word others Mostly addressing notes on ambiguous syntax and spurious newlines. --- src/libstd/keyword_docs.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 5c3a2b18e1cba..a1f594d5244f9 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -53,7 +53,7 @@ mod as_keyword { } /// Constants must be explicitly typed, unlike with `let` you can't ignore its type and let the /// compiler figure it out. Any constant value can be defined in a const, which in practice happens /// to be most things that would be reasonable to have a constant. For example, you can't have a -/// File as a const. +/// File as a `const`. /// /// The only lifetime allowed in a constant is 'static, which is the lifetime that encompasses all /// others in a Rust program. For example, if you wanted to define a constant string, it would look @@ -214,8 +214,9 @@ mod let_keyword { } /// } /// ``` /// -/// Another shortcut for struct instantiation is available when you need to make a new struct that -/// shares most of a previous struct's values called struct update syntax: +/// Another shortcut for struct instantiation is available, used when you need to make a new +/// struct that has the same values as most of a previous struct of the same type, called struct +/// update syntax: /// /// ```rust /// # struct Foo { field1: String, field2: () } @@ -229,10 +230,9 @@ mod let_keyword { } /// Tuple structs are instantiated in the same way as tuples themselves, except with the struct's /// name as a prefix: `Foo(123, false, 0.1)`. /// -/// Empty structs are instantiated with just their name and nothing else. `let thing = +/// Empty structs are instantiated with just their name, and don't need anything else. `let thing = /// EmptyStruct;` /// -/// /// # Style conventions /// /// Structs are always written in CamelCase, with few exceptions. While the trailing comma on a @@ -245,5 +245,4 @@ mod let_keyword { } /// [`PhantomData`]: marker/struct.PhantomData.html /// [book]: https://doc.rust-lang.org/book/second-edition/ch05-01-defining-structs.html /// [reference]: https://doc.rust-lang.org/reference/items/structs.html - mod struct_keyword { } From f8d6261f9bc3ae9d11a34f194d8593556965a537 Mon Sep 17 00:00:00 2001 From: iirelu Date: Wed, 5 Sep 2018 19:12:20 +0200 Subject: [PATCH 05/54] Add docs for `crate` keyword I think it might be used in some other things, but I'm not fluent enough at sifting through the rust compiler's source code to find every use of a specific keyword. This leaves the question of how to document the `extern` keyword, what with how much overlap it has with `crate`, but that's used with ABI stuff so that should be fine. --- src/libstd/keyword_docs.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index a1f594d5244f9..61b30d94e5a83 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -90,6 +90,40 @@ mod as_keyword { } /// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html mod const_keyword { } +#[doc(keyword = "crate")] +// +/// The `crate` keyword. +/// +/// The primary use of the `crate` keyword is as a part of `extern crate` declarations, which are +/// used to specify a dependency on a crate external to the one it's declared in. Crates are the +/// fundamental compilation unit of Rust code, and can be seen as libraries or projects. More can +/// be read about crates in the [Reference]. +/// +/// ```rust ignore +/// extern crate rand; +/// extern crate my_crate as thing; +/// extern crate std; // implicitly added to the root of every Rust project +/// ``` +/// +/// The `as` keyword can be used to change what the crate is referred to as in your project. If a +/// crate name includes a dash, it is implicitly imported with the dashes replaced by underscores. +/// +/// `crate` is also used as in conjunction with [`pub`] to signify that the item it's attached to +/// is public only to other members of the same crate it's in. +/// +/// ```rust +/// # #[allow(unused_imports)] +/// pub(crate) use std::io::Error as IoError; +/// pub(crate) enum CoolMarkerType { } +/// pub struct PublicThing { +/// pub(crate) semi_secret_thing: bool, +/// } +/// ``` +/// +/// [Reference]: https://doc.rust-lang.org/reference/items/extern-crates.html +/// [`pub`]: keyword.pub.html +mod crate_keyword { } + #[doc(keyword = "fn")] // /// The `fn` keyword. From f15a1ec45dbc0f24bdc2eef3e4d7d5a16fa4af1a Mon Sep 17 00:00:00 2001 From: iirelu Date: Thu, 6 Sep 2018 20:44:29 +0200 Subject: [PATCH 06/54] Add keyword docs on `enum` --- src/libstd/keyword_docs.rs | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 61b30d94e5a83..5026ca4d72264 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -124,6 +124,61 @@ mod const_keyword { } /// [`pub`]: keyword.pub.html mod crate_keyword { } +#[doc(keyword = "enum")] +// +/// For defining enumerations. +/// +/// Enums in Rust are similar to those of other compiled languages like C, but have important +/// differences that make them considerably more powerful. What Rust calls enums are more commonly +/// known as Algebraic Data Types if you're coming from a functional programming background, but +/// the important part is that data can go with the enum variants. +/// +/// ```rust +/// # struct Coord; +/// enum SimpleEnum { +/// FirstVariant, +/// SecondVariant, +/// ThirdVariant, +/// } +/// +/// enum Location { +/// Unknown, +/// Anonymous, +/// Known(Coord), +/// } +/// +/// enum ComplexEnum { +/// Nothing, +/// Something(u32), +/// LotsOfThings { +/// usual_struct_stuff: bool, +/// blah: String, +/// } +/// } +/// +/// enum EmptyEnum { } +/// ``` +/// +/// The first enum shown is the usual kind of enum you'd find in a C-style language. The second +/// shows off a hypothetical example of something storing location data, with Coord being any other +/// type that's needed, for example a struct. The third example demonstrates the kind of variant a +/// variant can store, ranging from nothing, to a tuple, to an anonymous struct. +/// +/// Instantiating enum variants involves explicitly using the enum's name as its namespace, +/// followed by one of its variants. `SimpleEnum::SecondVariant` would be an example from above. +/// When data follows along with a variant, such as with rust's built-in [`Option`] type, the data +/// is added as the type describes, for example `Option::Some(123)`. The same follows with +/// struct-like variants, with things looking like `ComplexEnum::LotsOfThings { usual_struct_stuff: +/// true, blah: "hello!".to_string(), }`. Empty Enums are similar to () in that they cannot be +/// instantiated at all, and are used mainly to mess with the type system in interesting ways. +/// +/// For more information, take a look at the [Rust Book] or the [Reference] +/// +/// [`Option`]: option/enum.Option.html +/// [Rust Book]: https://doc.rust-lang.org/book/second-edition/ch06-01-defining-an-enum.html +/// [Reference]: https://doc.rust-lang.org/reference/items/enumerations.html +mod enum_keyword { } + #[doc(keyword = "fn")] // /// The `fn` keyword. From f91ad440efdf4730946c21f17acc3e1c920dd894 Mon Sep 17 00:00:00 2001 From: iirelu Date: Sun, 9 Sep 2018 13:23:34 +0200 Subject: [PATCH 07/54] Add docs on `extern` keyword --- src/libstd/keyword_docs.rs | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 5026ca4d72264..a09917afbad0a 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -179,6 +179,48 @@ mod crate_keyword { } /// [Reference]: https://doc.rust-lang.org/reference/items/enumerations.html mod enum_keyword { } +#[doc(keyword = "extern")] +// +/// For external connections in Rust code. +/// +/// The `extern` keyword is used in two places in Rust. One is in conjunction with the [`crate`] +/// keyword to make your Rust code aware of other Rust crates in your project, i.e. `extern crate +/// lazy_static;`. The other use is in foreign function interfaces (FFI). +/// +/// `extern` is used in two different contexts within FFI. The first is in the form of external +/// blcoks, for declaring function interfaces that Rust code can call foreign code by. +/// +/// ```rust ignore +/// #[link(name = "my_c_library")] +/// extern "C" { +/// fn my_c_function(x: i32) -> bool; +/// } +/// ``` +/// +/// This code would attempt to link with libmy_c_library.so on unix-like systems and +/// my_c_library.dll on Windows at runtime, and panic if it can't find something to link to. Rust +/// code could then use `my_c_function` as if it were any other unsafe Rust function. Working with +/// non-Rust languages and FFI is inherently unsafe, so wrappers are usually built around C APIs. +/// +/// The mirror use case of FFI is also done via the `extern` keyword: +/// +/// ```rust +/// # #![allow(private_no_mangle_fns)] +/// #[no_mangle] +/// pub extern fn callable_from_c(x: i32) -> bool { +/// x % 3 == 0 +/// } +/// ``` +/// +/// If compiled as a dylib, the resulting .so could then be linked to from a C library, and the +/// function could be used as if it was from any other library. +/// +/// For more information on FFI, check the [Rust book] or the [Reference]. +/// +/// [Rust book]: https://doc.rust-lang.org/book/second-edition/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code +/// [Reference]: https://doc.rust-lang.org/reference/items/external-blocks.html +mod extern_keyword { } + #[doc(keyword = "fn")] // /// The `fn` keyword. From a5c4a382b7f0f9bb6a98001a6e5ffd9ab8ff3d70 Mon Sep 17 00:00:00 2001 From: iirelu Date: Sun, 9 Sep 2018 15:44:59 +0200 Subject: [PATCH 08/54] Expand fn keyword docs --- src/libstd/keyword_docs.rs | 66 ++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index a09917afbad0a..0cf524ab0dc2a 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -223,21 +223,73 @@ mod extern_keyword { } #[doc(keyword = "fn")] // -/// The `fn` keyword. +/// The keyword for defining functions. /// -/// The `fn` keyword is used to declare a function. +/// Functions are the primary way code is executed within Rust. Function blocks, usually just +/// called functions, can be defined in a variety of different places and be assigned many +/// different attributes and modifiers. /// -/// Example: +/// Standalone functions that just sit within a module not attached to anything else are common, +/// but most functions will end up being inside [`impl`] blocks, either on another type itself, or +/// as a trait impl for that type. /// /// ```rust -/// fn some_function() { -/// // code goes in here +/// fn standalone_function() { +/// // code +/// } +/// +/// pub fn public_thing(argument: bool) -> String { +/// // code +/// # "".to_string() +/// } +/// +/// struct Thing { +/// foo: i32, +/// } +/// +/// impl Thing { +/// pub fn new() -> Self { +/// Self { +/// foo: 42, +/// } +/// } /// } /// ``` /// -/// For more information about functions, take a look at the [Rust Book][book]. +/// See docs on [`impl`] and [`self`] for relevant details on those. +/// +/// In addition to presenting fixed types in the form of `fn name(arg: type, ..) -> return_type`, +/// functions can also declare a list of type parameters along with trait bounds that they fall +/// into. /// -/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html +/// ```rust +/// fn generic_function(x: T) -> (T, T, T) { +/// (x.clone(), x.clone(), x.clone()) +/// } +/// +/// fn generic_where(x: T) -> T +/// where T: std::ops::Add + Copy +/// { +/// x + x + x +/// } +/// ``` +/// +/// Declaring trait bounds in the angle brackets is functionally identical to using a [`where`] +/// clause, but `where` is preferred due to it being easier to understand at a glance. +/// +/// Along with being made public via [`pub`], `fn` can also have an [`extern`] added for use in +/// FFI. +/// +/// For more information on the various types of functions and how they're used, consult the [Rust +/// book] or the [Reference]. +/// +/// [`impl`]: keyword.impl.html +/// [`self`]: keyword.self.html +/// [`where`]: keyword.where.html +/// [`pub`]: keyword.pub.html +/// [`extern`]: keyword.extern.html +/// [Rust book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html +/// [Reference]: https://doc.rust-lang.org/reference/items/functions.html mod fn_keyword { } #[doc(keyword = "let")] From f7a66388f3f58d679eaee4c89dbde1f8b26a009e Mon Sep 17 00:00:00 2001 From: iirelu Date: Mon, 10 Sep 2018 19:36:27 +0200 Subject: [PATCH 09/54] Document `for` keyword --- src/libstd/keyword_docs.rs | 71 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 0cf524ab0dc2a..74dcf665c03b3 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -292,6 +292,77 @@ mod extern_keyword { } /// [Reference]: https://doc.rust-lang.org/reference/items/functions.html mod fn_keyword { } +#[doc(keyword = "for")] +// +/// The `for` keyword. +/// +/// `for` is primarily used in for-in-loops, but it has a few other pieces of syntactic uses such as +/// `impl Trait for Type` (see [`impl`] for more info on that). for-in-loops, or to be more +/// precise, iterator loops, are a simple syntactic sugar over an exceedingly common practice +/// within Rust, which is to loop over an iterator until that iterator returns None (or [`break`] +/// is called). +/// +/// ```rust +/// for i in 0..5 { +/// println!("{}", i * 2); +/// } +/// +/// for i in std::iter::repeat(5) { +/// println!("turns out {} never stops being 5", i); +/// break; // would loop forever otherwise +/// } +/// +/// 'outer: for x in 5..50 { +/// for y in 0..10 { +/// if x == y { +/// break 'outer; +/// } +/// } +/// } +/// ``` +/// +/// As shown in the example above, `for` loops (along with all other loops) can be tagged, using +/// similar syntax to lifetimes (only visually similar, entirely distinct in practice). Giving the +/// same tag to `break` breaks the tagged loop, which is useful for inner loops. It is definitely +/// not a goto. +/// +/// A `for` loop expands as shown: +/// +/// ```rust +/// # fn code() { } +/// # let iterator = 0..2; +/// for loop_variable in iterator { +/// code() +/// } +/// ``` +/// +/// ```rust +/// # fn code() { } +/// # let iterator = 0..2; +/// { +/// let mut _iter = std::iter::IntoIterator::into_iter(iterator); +/// loop { +/// match _iter.next() { +/// Some(loop_variable) => { +/// code() +/// }, +/// None => break, +/// } +/// } +/// } +/// ``` +/// +/// More details on the functionality shown can be seen at the [`IntoIterator`] docs. +/// +/// For more information on for-loops, see the [Rust book] or the [Reference]. +/// +/// [`impl`]: keyword.impl.html +/// [`break`]: keyword.break.html +/// [`IntoIterator`]: iter/trait.IntoIterator.html +/// [Rust book]: https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html#looping-through-a-collection-with-for +/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops +mod for_keyword { } + #[doc(keyword = "let")] // /// The `let` keyword. From 5d05ae7235743c150ca1aa96c31f0421caf5440f Mon Sep 17 00:00:00 2001 From: iirelu Date: Wed, 12 Sep 2018 16:43:13 +0200 Subject: [PATCH 10/54] Document `if` keyword. --- src/libstd/keyword_docs.rs | 78 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 74dcf665c03b3..d1f799fc9808f 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -363,6 +363,84 @@ mod fn_keyword { } /// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops mod for_keyword { } +#[doc(keyword = "if")] +// +/// If statements and expressions. +/// +/// `if` is a familiar construct to most programmers, and is the main way you'll often do logic in +/// your code. However, unlike in most languages, `if` blocks can also act as expressions. +/// +/// ```rust +/// # let rude = true; +/// if 1 == 2 { +/// println!("whoops, mathematics broke"); +/// } else { +/// println!("everything's fine!"); +/// } +/// +/// let greeting = if rude { +/// "sup nerd." +/// } else { +/// "hello, friend!" +/// }; +/// +/// if let Ok(x) = "123".parse::() { +/// println!("{} double that and you get {}!", greeting, x * 2); +/// } +/// ``` +/// +/// Shown above are the three typical forms an `if` block comes in. First is the usual kind of +/// thing you'd see in many languages, with an optional `else` block. Second uses `if` as an +/// expression, which is only possible if all branches return the same type. An `if` expression can +/// be used everywhere you'd expect. The third kind of `if` block is an `if let` block, which +/// behaves similarly to using a [`match`] expression: +/// +/// ```rust +/// if let Some(x) = Some(123) { +/// // code +/// # let _ = x; +/// } else { +/// // something else +/// } +/// +/// match Some(123) { +/// Some(x) => { +/// // code +/// # let _ = x; +/// }, +/// _ => { +/// // something else +/// }, +/// } +/// ``` +/// +/// See [`let`] for more information on pattern bindings. +/// +/// Each kind of `if` expression can be mixed and matched as needed. +/// +/// ```rust +/// if true == false { +/// println!("oh no"); +/// } else if "something" == "other thing" { +/// println!("oh dear"); +/// } else if let Some(200) = "blarg".parse::().ok() { +/// println!("uh oh"); +/// } else { +/// println!("phew, nothing's broken"); +/// } +/// ``` +/// +/// The `if` keyword is used in one other place in Rust, namely as a part of pattern matching +/// itself, allowing patterns such as `Some(x) if x > 200` to be used. +/// +/// For more information on `if` expressions, see the [Rust book] or the [Reference]. +/// +/// [`match`]: keyword.match.html +/// [`let`]: keyword.let.html +/// [Rust book]: https://doc.rust-lang.org/stable/book/2018-edition/ch03-05-control-flow.html#if-expressions +/// [Reference]: https://doc.rust-lang.org/reference/expressions/if-expr.html +mod if_keyword { } + #[doc(keyword = "let")] // /// The `let` keyword. From 5393b277aa769b6d5eab2a18f13cb99a333b4f88 Mon Sep 17 00:00:00 2001 From: iirelu Date: Fri, 14 Sep 2018 14:40:26 +0200 Subject: [PATCH 11/54] Incorporate keyword doc PR critique --- src/libstd/keyword_docs.rs | 67 ++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index d1f799fc9808f..fbe7e244381c5 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -10,7 +10,7 @@ #[doc(keyword = "as")] // -/// The type coercion keyword. +/// The keyword for casting types. /// /// `as` is most commonly used to turn primitive types into other primitive types, but it has other /// uses that include turning pointers into addresses, addresses into pointers, and pointers into @@ -24,15 +24,20 @@ /// assert_eq!(true as u8 + thing2 as u8, 100); /// ``` /// -/// In general, any coercion that can be performed via writing out type hints can also be done -/// using `as`, so instead of writing `let x: u32 = 123`, you can write `let x = 123 as u32` (Note: -/// `let x = 123u32` would be best in that situation). The same is not true in the other direction, -/// however, explicitly using `as` allows a few more coercions that aren't allowed implicitly, such -/// as changing the type of a raw pointer or turning closures into raw pointers. +/// In general, any cast that can be performed via ascribing the type can also be done using `as`, +/// so instead of writing `let x: u32 = 123`, you can write `let x = 123 as u32` (Note: `let x: u32 +/// = 123` would be best in that situation). The same is not true in the other direction, however, +/// explicitly using `as` allows a few more coercions that aren't allowed implicitly, such as +/// changing the type of a raw pointer or turning closures into raw pointers. +/// +/// Other places `as` is used include as extra syntax for [`crate`] and [`use`], to change the name +/// something is imported as. /// /// For more information on what `as` is capable of, see the [Reference] /// /// [Reference]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions +/// [`crate`]: keyword.crate.html +/// [`use`]: keyword.use.html mod as_keyword { } #[doc(keyword = "const")] @@ -52,12 +57,12 @@ mod as_keyword { } /// /// Constants must be explicitly typed, unlike with `let` you can't ignore its type and let the /// compiler figure it out. Any constant value can be defined in a const, which in practice happens -/// to be most things that would be reasonable to have a constant. For example, you can't have a -/// File as a `const`. +/// to be most things that would be reasonable to have a constant (barring `const fn`s, coming +/// soon). For example, you can't have a File as a `const`. /// -/// The only lifetime allowed in a constant is 'static, which is the lifetime that encompasses all -/// others in a Rust program. For example, if you wanted to define a constant string, it would look -/// like this: +/// The only lifetime allowed in a constant is `'static`, which is the lifetime that encompasses +/// all others in a Rust program. For example, if you wanted to define a constant string, it would +/// look like this: /// /// ```rust /// const WORDS: &'static str = "hello rust!"; @@ -73,9 +78,8 @@ mod as_keyword { } /// to which one should be used at which times. To put it simply, constants are inlined wherever /// they're used, making using them identical to simply replacing the name of the const with its /// value. Static variables on the other hand point to a single location in memory, which all -/// accesses share. This means that, unlike with constants, they can't have destructors, but it -/// also means that (via unsafe code) they can be mutable, which is useful for the rare situations -/// in which you can't avoid using global state. +/// accesses share. This means that, unlike with constants, they can't have destructors, and act as +/// a single value across the entire codebase. /// /// Constants, as with statics, should always be in SCREAMING_SNAKE_CASE. /// @@ -130,8 +134,8 @@ mod crate_keyword { } /// /// Enums in Rust are similar to those of other compiled languages like C, but have important /// differences that make them considerably more powerful. What Rust calls enums are more commonly -/// known as Algebraic Data Types if you're coming from a functional programming background, but -/// the important part is that data can go with the enum variants. +/// known as Algebraic Data Types if you're coming from a functional programming background. The +/// important detail is that each enum variant can have data to go along with it. /// /// ```rust /// # struct Coord; @@ -160,9 +164,9 @@ mod crate_keyword { } /// ``` /// /// The first enum shown is the usual kind of enum you'd find in a C-style language. The second -/// shows off a hypothetical example of something storing location data, with Coord being any other -/// type that's needed, for example a struct. The third example demonstrates the kind of variant a -/// variant can store, ranging from nothing, to a tuple, to an anonymous struct. +/// shows off a hypothetical example of something storing location data, with `Coord` being any +/// other type that's needed, for example a struct. The third example demonstrates the kind of +/// data a variant can store, ranging from nothing, to a tuple, to an anonymous struct. /// /// Instantiating enum variants involves explicitly using the enum's name as its namespace, /// followed by one of its variants. `SimpleEnum::SecondVariant` would be an example from above. @@ -188,7 +192,7 @@ mod enum_keyword { } /// lazy_static;`. The other use is in foreign function interfaces (FFI). /// /// `extern` is used in two different contexts within FFI. The first is in the form of external -/// blcoks, for declaring function interfaces that Rust code can call foreign code by. +/// blocks, for declaring function interfaces that Rust code can call foreign code by. /// /// ```rust ignore /// #[link(name = "my_c_library")] @@ -197,8 +201,8 @@ mod enum_keyword { } /// } /// ``` /// -/// This code would attempt to link with libmy_c_library.so on unix-like systems and -/// my_c_library.dll on Windows at runtime, and panic if it can't find something to link to. Rust +/// This code would attempt to link with `libmy_c_library.so` on unix-like systems and +/// `my_c_library.dll` on Windows at runtime, and panic if it can't find something to link to. Rust /// code could then use `my_c_function` as if it were any other unsafe Rust function. Working with /// non-Rust languages and FFI is inherently unsafe, so wrappers are usually built around C APIs. /// @@ -275,7 +279,8 @@ mod extern_keyword { } /// ``` /// /// Declaring trait bounds in the angle brackets is functionally identical to using a [`where`] -/// clause, but `where` is preferred due to it being easier to understand at a glance. +/// clause. It's up to the programmer to decide which works better in each situation, but `where` +/// tends to be better when things get longer than one line. /// /// Along with being made public via [`pub`], `fn` can also have an [`extern`] added for use in /// FFI. @@ -475,8 +480,8 @@ mod let_keyword { } // /// The keyword used to define structs. /// -/// Structs in Rust come in three flavours: Regular structs, tuple structs, -/// and empty structs. +/// Structs in Rust come in three flavours: Structs with named fields, tuple structs, and unit +/// structs. /// /// ```rust /// struct Regular { @@ -487,7 +492,7 @@ mod let_keyword { } /// /// struct Tuple(u32, String); /// -/// struct Empty; +/// struct Unit; /// ``` /// /// Regular structs are the most commonly used. Each field defined within them has a name and a @@ -501,14 +506,14 @@ mod let_keyword { } /// individual variables, the same syntax is used as with regular tuples, namely `foo.0`, `foo.1`, /// etc, starting at zero. /// -/// Empty structs, or unit-like structs, are most commonly used as markers, for example -/// [`PhantomData`]. Empty structs have a size of zero bytes, but unlike empty enums they can be -/// instantiated, making them similar to the unit type `()`. Unit-like structs are useful when you -/// need to implement a trait on something, but don't need to store any data inside it. +/// Unit structs are most commonly used as marker. They have a size of zero bytes, but unlike empty +/// enums they can be instantiated, making them isomorphic to the unit type `()`. Unit structs are +/// useful when you need to implement a trait on something, but don't need to store any data inside +/// it. /// /// # Instantiation /// -/// Structs can be instantiated in a manner of different ways, each of which can be mixed and +/// Structs can be instantiated in different ways, all of which can be mixed and /// matched as needed. The most common way to make a new struct is via a constructor method such as /// `new()`, but when that isn't available (or you're writing the constructor itself), struct /// literal syntax is used: From 738e58d57e0911a02c076f2b6064a7f471ecb0c1 Mon Sep 17 00:00:00 2001 From: iirelu Date: Wed, 19 Sep 2018 17:01:07 +0200 Subject: [PATCH 12/54] Document impl keyword This commit also splits out linky-line-thingies into two lines, which judging from the source code for tidy, should be enough to make it shut up and accept me for who I am, dammit. --- src/libstd/keyword_docs.rs | 76 +++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index fbe7e244381c5..6f8ff1a4b71d7 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -35,7 +35,8 @@ /// /// For more information on what `as` is capable of, see the [Reference] /// -/// [Reference]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions +/// [Reference]: +/// https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions /// [`crate`]: keyword.crate.html /// [`use`]: keyword.use.html mod as_keyword { } @@ -90,7 +91,8 @@ mod as_keyword { } /// /// [`static`]: keyword.static.html /// [pointer]: primitive.pointer.html -/// [Rust Book]: https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants +/// [Rust Book]: +/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants /// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html mod const_keyword { } @@ -221,7 +223,8 @@ mod enum_keyword { } /// /// For more information on FFI, check the [Rust book] or the [Reference]. /// -/// [Rust book]: https://doc.rust-lang.org/book/second-edition/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code +/// [Rust book]: +/// https://doc.rust-lang.org/book/second-edition/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code /// [Reference]: https://doc.rust-lang.org/reference/items/external-blocks.html mod extern_keyword { } @@ -364,7 +367,8 @@ mod fn_keyword { } /// [`impl`]: keyword.impl.html /// [`break`]: keyword.break.html /// [`IntoIterator`]: iter/trait.IntoIterator.html -/// [Rust book]: https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html#looping-through-a-collection-with-for +/// [Rust book]: +/// https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html#looping-through-a-collection-with-for /// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops mod for_keyword { } @@ -442,10 +446,72 @@ mod for_keyword { } /// /// [`match`]: keyword.match.html /// [`let`]: keyword.let.html -/// [Rust book]: https://doc.rust-lang.org/stable/book/2018-edition/ch03-05-control-flow.html#if-expressions +/// [Rust book]: +/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-05-control-flow.html#if-expressions /// [Reference]: https://doc.rust-lang.org/reference/expressions/if-expr.html mod if_keyword { } +#[doc(keyword = "impl")] +// +/// The implementation-defining keyword. +/// +/// The `impl` keyword is primarily used for defining implementations on types. There are two kinds +/// of implementations: Inherent implementations and trait implementations. Inherent +/// implementations define functions that operate on a type, known in object-oriented languages as +/// methods. Trait implementations are used to give a type a trait, and implement any of the +/// required associated items or methods that it requires. +/// +/// ```rust +/// struct Example { +/// number: i32, +/// } +/// +/// impl Example { +/// fn boo() { +/// println!("boo! Example::boo() was called!"); +/// } +/// +/// fn answer(&mut self) { +/// self.number += 42; +/// } +/// +/// fn get_number(&self) -> i32 { +/// self.number +/// } +/// } +/// +/// trait Thingy { +/// fn do_thingy(&self); +/// } +/// +/// impl Thingy for Example { +/// fn do_thingy(&self) { +/// println!("doing a thing! also, number is {}!", self.number); +/// } +/// } +/// ``` +/// +/// For more information on implementations, see the [Rust book][book1] or the [Reference]. +/// +/// The other use of the `impl` keyword is in `impl Trait` syntax, which can be seen as a shorthand +/// for "a concrete type that implements this trait". Its primary use is working with closures, +/// which have type definitions generated at compile time that can't be simply typed out. +/// +/// ```rust +/// fn thing_returning_closure() -> impl Fn(i32) -> bool { +/// println!("here's a closure for you!"); +/// |x: i32| x % 3 == 0 +/// } +/// ``` +/// +/// For more information on `impl Trait` syntax, see the [Rust book][book2]. +/// +/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch05-03-method-syntax.html +/// [Reference]: https://doc.rust-lang.org/reference/items/implementations.html +/// [book2]: +/// https://doc.rust-lang.org/stable/book/2018-edition/ch10-02-traits.html#returning-traits +mod impl_keyword { } + #[doc(keyword = "let")] // /// The `let` keyword. From 165690b7db9183945230d43f73c2042a34ed09cf Mon Sep 17 00:00:00 2001 From: iirelu Date: Wed, 19 Sep 2018 18:08:22 +0200 Subject: [PATCH 13/54] Rework `let` keyword docs It didn't strictly need to be reworked and I'm not sure my version is better, but oh well, I'm doing it for consistency. --- src/libstd/keyword_docs.rs | 62 +++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 6f8ff1a4b71d7..d2a22334a954c 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -514,32 +514,66 @@ mod impl_keyword { } #[doc(keyword = "let")] // -/// The `let` keyword. +/// The variable binding keyword. /// -/// The `let` keyword is used to declare a variable. -/// -/// Example: +/// The primary use for the `let` keyword is in `let` statements, which are used to introduce a new +/// set of variables into the current scope, as given by a pattern. /// /// ```rust /// # #![allow(unused_assignments)] -/// let x = 3; // We create a variable named `x` with the value `3`. +/// let thing1: i32 = 100; +/// let thing2 = 200 + thing1; +/// +/// let mut changing_thing = true; +/// changing_thing = false; +/// +/// let (part1, part2) = ("first", "second"); +/// +/// struct Example { +/// a: bool, +/// b: u64, +/// } +/// +/// let Example { a, b: _ } = Example { +/// a: true, +/// b: 10004, +/// }; +/// assert!(a); /// ``` /// -/// By default, all variables are **not** mutable. If you want a mutable variable, -/// you'll have to use the `mut` keyword. +/// The pattern is most commonly a single variable, which means no pattern matching is done and +/// the expression given is bound to the variable. Apart from that, patterns used in `let` bindings +/// can be as complicated as needed, given that the pattern is exhaustive. See the [Rust +/// book][book1] for more information on pattern matching. The type of the pattern is optionally +/// given afterwards, but if left blank is automatically inferred by the compiler if possible. /// -/// Example: +/// Variables in Rust are immutable by default, and require the [`mut`] keyword to be made mutable. /// -/// ```rust -/// # #![allow(unused_assignments)] -/// let mut x = 3; // We create a mutable variable named `x` with the value `3`. +/// Multiple variables can be defined with the same name, known as shadowing. This doesn't affect +/// the original variable in any way beyond being unable to directly access it beyond the point of +/// shadowing. It continues to remain in scope, getting dropped only when it falls out of scope. +/// Shadowed variables don't need to have the same type as the variables shadowing them. /// -/// x += 4; // `x` is now equal to `7`. +/// ```rust +/// let shadowing_example = true; +/// let shadowing_example = 123.4; +/// let shadowing_example = shadowing_example as u32; +/// let mut shadowing_example = format!("cool! {}", shadowing_example); +/// shadowing_example += " something else!"; // not shadowing /// ``` /// -/// For more information about the `let` keyword, take a look at the [Rust Book][book]. +/// Other places the `let` keyword is used include along with [`if`], in the form of `if let` +/// expressions. They're useful if the pattern being matched isn't exhaustive, such as with +/// enumerations. +/// +/// For more information on the `let` keyword, see the [Rust book] or the [Reference] /// -/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html +/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch06-02-match.html +/// [`mut`]: keyword.mut.html +/// [`if`]: keyword.if.html +/// [book2]: +/// https://doc.rust-lang.org/stable/book/2018-edition/ch18-01-all-the-places-for-patterns.html#let-statements +/// [Reference]: https://doc.rust-lang.org/reference/statements.html#let-statements mod let_keyword { } #[doc(keyword = "struct")] From 76a353b160cdb8551eac8affc8299df85da50558 Mon Sep 17 00:00:00 2001 From: iirelu Date: Mon, 24 Sep 2018 16:42:43 +0200 Subject: [PATCH 14/54] Add keyword docs for `loop`. --- src/libstd/keyword_docs.rs | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index d2a22334a954c..63df5401b922a 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -576,6 +576,51 @@ mod impl_keyword { } /// [Reference]: https://doc.rust-lang.org/reference/statements.html#let-statements mod let_keyword { } +#[doc(keyword = "loop")] +// +/// The loop-defining keyword. +/// +/// `loop` is used to define the simplest kind of loop supported in Rust. It runs the code inside +/// it until the code uses `break` or the program exits. +/// +/// ```rust +/// loop { +/// println!("hello world forever!"); +/// # break; +/// } +/// +/// let mut i = 0; +/// loop { +/// println!("i is {}", i); +/// if i > 10 { +/// break; +/// } +/// i += 1; +/// } +/// ``` +/// +/// Unlike the other kinds of loops in Rust (`while`, `while let`, and `for`), loops can be used as +/// expressions that return values via `break`. +/// +/// ```rust +/// let mut i = 1; +/// let something = loop { +/// i *= 2; +/// if i > 100 { +/// break i; +/// } +/// }; +/// assert_eq!(something, 128); +/// ``` +/// +/// Every `break` in a loop has to have the same type. When it's not explicitly giving something, +/// `break;` returns `()`. +/// +/// For more information on `loop` and loops in general, see the [Reference]. +/// +/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html +mod loop_keyword { } + #[doc(keyword = "struct")] // /// The keyword used to define structs. From 50f631ce80ac3d04d52e4d6b3b4c5126ac9c1009 Mon Sep 17 00:00:00 2001 From: iirelu Date: Wed, 26 Sep 2018 16:52:47 +0200 Subject: [PATCH 15/54] Removed dead links to unwritten keyword docs Most of these will eventually be filled, but right now travis-ci enjoys complaining about the fact that there's links that lead nowhere, so they're gone. Hopefully someone remembers to re-add them later. --- src/libstd/keyword_docs.rs | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 63df5401b922a..cd7b38952891f 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -30,7 +30,7 @@ /// explicitly using `as` allows a few more coercions that aren't allowed implicitly, such as /// changing the type of a raw pointer or turning closures into raw pointers. /// -/// Other places `as` is used include as extra syntax for [`crate`] and [`use`], to change the name +/// Other places `as` is used include as extra syntax for [`crate`] and `use`, to change the name /// something is imported as. /// /// For more information on what `as` is capable of, see the [Reference] @@ -38,7 +38,6 @@ /// [Reference]: /// https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions /// [`crate`]: keyword.crate.html -/// [`use`]: keyword.use.html mod as_keyword { } #[doc(keyword = "const")] @@ -75,7 +74,7 @@ mod as_keyword { } /// const WORDS: &str = "hello convenience!"; /// ``` /// -/// `const` items looks remarkably similar to [`static`] items, which introduces some confusion as +/// `const` items looks remarkably similar to `static` items, which introduces some confusion as /// to which one should be used at which times. To put it simply, constants are inlined wherever /// they're used, making using them identical to simply replacing the name of the const with its /// value. Static variables on the other hand point to a single location in memory, which all @@ -89,7 +88,6 @@ mod as_keyword { } /// /// For more detail on `const`, see the [Rust Book] or the [Reference] /// -/// [`static`]: keyword.static.html /// [pointer]: primitive.pointer.html /// [Rust Book]: /// https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants @@ -114,7 +112,7 @@ mod const_keyword { } /// The `as` keyword can be used to change what the crate is referred to as in your project. If a /// crate name includes a dash, it is implicitly imported with the dashes replaced by underscores. /// -/// `crate` is also used as in conjunction with [`pub`] to signify that the item it's attached to +/// `crate` is also used as in conjunction with `pub` to signify that the item it's attached to /// is public only to other members of the same crate it's in. /// /// ```rust @@ -127,7 +125,6 @@ mod const_keyword { } /// ``` /// /// [Reference]: https://doc.rust-lang.org/reference/items/extern-crates.html -/// [`pub`]: keyword.pub.html mod crate_keyword { } #[doc(keyword = "enum")] @@ -263,8 +260,6 @@ mod extern_keyword { } /// } /// ``` /// -/// See docs on [`impl`] and [`self`] for relevant details on those. -/// /// In addition to presenting fixed types in the form of `fn name(arg: type, ..) -> return_type`, /// functions can also declare a list of type parameters along with trait bounds that they fall /// into. @@ -281,20 +276,17 @@ mod extern_keyword { } /// } /// ``` /// -/// Declaring trait bounds in the angle brackets is functionally identical to using a [`where`] +/// Declaring trait bounds in the angle brackets is functionally identical to using a `where` /// clause. It's up to the programmer to decide which works better in each situation, but `where` /// tends to be better when things get longer than one line. /// -/// Along with being made public via [`pub`], `fn` can also have an [`extern`] added for use in +/// Along with being made public via `pub`, `fn` can also have an [`extern`] added for use in /// FFI. /// /// For more information on the various types of functions and how they're used, consult the [Rust /// book] or the [Reference]. /// /// [`impl`]: keyword.impl.html -/// [`self`]: keyword.self.html -/// [`where`]: keyword.where.html -/// [`pub`]: keyword.pub.html /// [`extern`]: keyword.extern.html /// [Rust book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html /// [Reference]: https://doc.rust-lang.org/reference/items/functions.html @@ -307,7 +299,7 @@ mod fn_keyword { } /// `for` is primarily used in for-in-loops, but it has a few other pieces of syntactic uses such as /// `impl Trait for Type` (see [`impl`] for more info on that). for-in-loops, or to be more /// precise, iterator loops, are a simple syntactic sugar over an exceedingly common practice -/// within Rust, which is to loop over an iterator until that iterator returns None (or [`break`] +/// within Rust, which is to loop over an iterator until that iterator returns None (or `break` /// is called). /// /// ```rust @@ -365,7 +357,6 @@ mod fn_keyword { } /// For more information on for-loops, see the [Rust book] or the [Reference]. /// /// [`impl`]: keyword.impl.html -/// [`break`]: keyword.break.html /// [`IntoIterator`]: iter/trait.IntoIterator.html /// [Rust book]: /// https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html#looping-through-a-collection-with-for @@ -402,7 +393,7 @@ mod for_keyword { } /// thing you'd see in many languages, with an optional `else` block. Second uses `if` as an /// expression, which is only possible if all branches return the same type. An `if` expression can /// be used everywhere you'd expect. The third kind of `if` block is an `if let` block, which -/// behaves similarly to using a [`match`] expression: +/// behaves similarly to using a `match` expression: /// /// ```rust /// if let Some(x) = Some(123) { @@ -423,8 +414,6 @@ mod for_keyword { } /// } /// ``` /// -/// See [`let`] for more information on pattern bindings. -/// /// Each kind of `if` expression can be mixed and matched as needed. /// /// ```rust @@ -444,8 +433,6 @@ mod for_keyword { } /// /// For more information on `if` expressions, see the [Rust book] or the [Reference]. /// -/// [`match`]: keyword.match.html -/// [`let`]: keyword.let.html /// [Rust book]: /// https://doc.rust-lang.org/stable/book/2018-edition/ch03-05-control-flow.html#if-expressions /// [Reference]: https://doc.rust-lang.org/reference/expressions/if-expr.html From 577dbc8519be61c1318b242c6c7fc15bbdf3b4b7 Mon Sep 17 00:00:00 2001 From: iirelu Date: Wed, 26 Sep 2018 17:06:11 +0200 Subject: [PATCH 16/54] Incorporate criticisms into keyword docs Thanks to @Centril for these. --- src/libstd/keyword_docs.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index cd7b38952891f..dc78accc69f88 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -10,7 +10,7 @@ #[doc(keyword = "as")] // -/// The keyword for casting types. +/// The keyword for casting a value to a type. /// /// `as` is most commonly used to turn primitive types into other primitive types, but it has other /// uses that include turning pointers into addresses, addresses into pointers, and pointers into @@ -133,7 +133,7 @@ mod crate_keyword { } /// /// Enums in Rust are similar to those of other compiled languages like C, but have important /// differences that make them considerably more powerful. What Rust calls enums are more commonly -/// known as Algebraic Data Types if you're coming from a functional programming background. The +/// known as [Algebraic Data Types] if you're coming from a functional programming background. The /// important detail is that each enum variant can have data to go along with it. /// /// ```rust @@ -177,6 +177,7 @@ mod crate_keyword { } /// /// For more information, take a look at the [Rust Book] or the [Reference] /// +/// [Algebraic Data Types]: https://en.wikipedia.org/wiki/Algebraic_data_type /// [`Option`]: option/enum.Option.html /// [Rust Book]: https://doc.rust-lang.org/book/second-edition/ch06-01-defining-an-enum.html /// [Reference]: https://doc.rust-lang.org/reference/items/enumerations.html @@ -442,11 +443,14 @@ mod if_keyword { } // /// The implementation-defining keyword. /// -/// The `impl` keyword is primarily used for defining implementations on types. There are two kinds -/// of implementations: Inherent implementations and trait implementations. Inherent -/// implementations define functions that operate on a type, known in object-oriented languages as -/// methods. Trait implementations are used to give a type a trait, and implement any of the -/// required associated items or methods that it requires. +/// The `impl` keyword is primarily used to define implementations on types. Inherent +/// implementations are standalone, while trait implementations are used to implement traits for +/// types, or other traits. +/// +/// Functions and consts can both be defined in an implementation. A function defined in an +/// `impl` block can be standalone, meaning it would be called like `Foo::bar()`. If the function +/// takes `self`, `&self`, or `&mut self` as its first argument, it can also be called using +/// method-call syntax, a familiar feature to any object oriented programmer, like `foo.bar()`. /// /// ```rust /// struct Example { @@ -551,7 +555,8 @@ mod impl_keyword { } /// /// Other places the `let` keyword is used include along with [`if`], in the form of `if let` /// expressions. They're useful if the pattern being matched isn't exhaustive, such as with -/// enumerations. +/// enumerations. `while let` also exists, which runs a loop with a pattern matched value until +/// that pattern can't be matched. /// /// For more information on the `let` keyword, see the [Rust book] or the [Reference] /// From 619dfeb514d101ea167a850ef1cd338dc4759e23 Mon Sep 17 00:00:00 2001 From: iirelu Date: Wed, 26 Sep 2018 18:37:46 +0200 Subject: [PATCH 17/54] Remove the last broken link. Dangit. I really thought I got them all. --- src/libstd/keyword_docs.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index dc78accc69f88..1e801373736c5 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -538,7 +538,7 @@ mod impl_keyword { } /// book][book1] for more information on pattern matching. The type of the pattern is optionally /// given afterwards, but if left blank is automatically inferred by the compiler if possible. /// -/// Variables in Rust are immutable by default, and require the [`mut`] keyword to be made mutable. +/// Variables in Rust are immutable by default, and require the `mut` keyword to be made mutable. /// /// Multiple variables can be defined with the same name, known as shadowing. This doesn't affect /// the original variable in any way beyond being unable to directly access it beyond the point of @@ -561,7 +561,6 @@ mod impl_keyword { } /// For more information on the `let` keyword, see the [Rust book] or the [Reference] /// /// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch06-02-match.html -/// [`mut`]: keyword.mut.html /// [`if`]: keyword.if.html /// [book2]: /// https://doc.rust-lang.org/stable/book/2018-edition/ch18-01-all-the-places-for-patterns.html#let-statements From 63c471e10227944268ddf67973a584d68e314a8d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 27 Sep 2018 15:50:17 -0700 Subject: [PATCH 18/54] rustc: Tweak filenames encoded into metadata This commit is a fix for #54408 where on nightly right now whenever generics are inlined the path name listed for the inlined function's debuginfo is a relative path to the cwd, which surely doesn't exist! Previously on beta/stable the debuginfo mentioned an absolute path which still didn't exist, but more predictably didn't exist. The change between stable/nightly is that nightly is now compiled with `--remap-path-prefix` to give a deterministic prefix to all rustc-generated paths in debuginfo. By using `--remap-path-prefix` the previous logic would recognize that the cwd was remapped, causing the original relative path name of the standard library to get emitted. If `--remap-path-prefix` *wasn't* passed in then the logic would create an absolute path name and then create a new source file entry. The fix in this commit is to apply the "recreate the source file entry with an absolute path" logic a bit more aggresively. If the source file's name was remapped then we don't touch it, but otherwise we always take the working dir (which may have been remapped) and then join it to the file to ensure that we process all relative file names as well. The end result is that the standard library should have an absolute path for all file names in debuginfo (using our `--remap-path-prefix` argument) as it does on stable after this patch. Closes #54408 --- src/librustc_metadata/encoder.rs | 42 ++++++++----------- .../auxiliary/xcrate-generic.rs | 16 +++++++ .../remap_path_prefix/xcrate-generic.rs | 25 +++++++++++ 3 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs create mode 100644 src/test/codegen/remap_path_prefix/xcrate-generic.rs diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c36ae02ab54e0..292bf1daee22f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -340,7 +340,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); - let (working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir.clone(); + let (working_dir, _cwd_remapped) = self.tcx.sess.working_dir.clone(); let adapted = all_source_files.iter() .filter(|source_file| { @@ -349,32 +349,26 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { !source_file.is_imported() }) .map(|source_file| { - // When exporting SourceFiles, we expand all paths to absolute - // paths because any relative paths are potentially relative to - // a wrong directory. - // However, if a path has been modified via - // `--remap-path-prefix` we assume the user has already set - // things up the way they want and don't touch the path values - // anymore. match source_file.name { + // This path of this SourceFile has been modified by + // path-remapping, so we use it verbatim (and avoid + // cloning the whole map in the process). + _ if source_file.name_was_remapped => source_file.clone(), + + // Otherwise expand all paths to absolute paths because + // any relative paths are potentially relative to a + // wrong directory. FileName::Real(ref name) => { - if source_file.name_was_remapped || - (name.is_relative() && working_dir_was_remapped) { - // This path of this SourceFile has been modified by - // path-remapping, so we use it verbatim (and avoid cloning - // the whole map in the process). - source_file.clone() - } else { - let mut adapted = (**source_file).clone(); - adapted.name = Path::new(&working_dir).join(name).into(); - adapted.name_hash = { - let mut hasher: StableHasher = StableHasher::new(); - adapted.name.hash(&mut hasher); - hasher.finish() - }; - Lrc::new(adapted) - } + let mut adapted = (**source_file).clone(); + adapted.name = Path::new(&working_dir).join(name).into(); + adapted.name_hash = { + let mut hasher: StableHasher = StableHasher::new(); + adapted.name.hash(&mut hasher); + hasher.finish() + }; + Lrc::new(adapted) }, + // expanded code, not from a file _ => source_file.clone(), } diff --git a/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs b/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs new file mode 100644 index 0000000000000..6c477a407812a --- /dev/null +++ b/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs @@ -0,0 +1,16 @@ +// Copyright 2017 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. + +// ignore-tidy-linelength +// compile-flags: -g --remap-path-prefix={{cwd}}=/the/aux-cwd --remap-path-prefix={{src-base}}/remap_path_prefix/auxiliary=/the/aux-src + +#![crate_type = "lib"] + +pub fn foo() {} diff --git a/src/test/codegen/remap_path_prefix/xcrate-generic.rs b/src/test/codegen/remap_path_prefix/xcrate-generic.rs new file mode 100644 index 0000000000000..f206df9813165 --- /dev/null +++ b/src/test/codegen/remap_path_prefix/xcrate-generic.rs @@ -0,0 +1,25 @@ +// Copyright 2017 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. + +// ignore-windows +// ignore-tidy-linelength +// compile-flags: -g -C metadata=foo -C no-prepopulate-passes +// aux-build:xcrate-generic.rs + +#![crate_type = "lib"] + +extern crate xcrate_generic; + +pub fn foo() { + xcrate_generic::foo::(); +} + +// Here we check that local debuginfo is mapped correctly. +// CHECK: !DIFile(filename: "/the/aux-src/xcrate-generic.rs", directory: "") From e961d397cab900c55f8d8c104648852e2b63664e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 8 Oct 2018 22:51:37 +0200 Subject: [PATCH 19/54] Add line numbers option to rustdoc --- src/librustdoc/html/highlight.rs | 13 ++++--- src/librustdoc/html/render.rs | 1 + src/librustdoc/html/static/main.js | 42 ++++++++++++++++----- src/librustdoc/html/static/rustdoc.css | 18 +++++++++ src/librustdoc/html/static/themes/dark.css | 4 ++ src/librustdoc/html/static/themes/light.css | 4 ++ 6 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 5df4862290e3c..bd4cfe51ea72f 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -28,9 +28,12 @@ use syntax::parse; use syntax_pos::{Span, FileName}; /// Highlights `src`, returning the HTML output. -pub fn render_with_highlighting(src: &str, class: Option<&str>, - extension: Option<&str>, - tooltip: Option<(&str, &str)>) -> String { +pub fn render_with_highlighting( + src: &str, + class: Option<&str>, + extension: Option<&str>, + tooltip: Option<(&str, &str)>, +) -> String { debug!("highlighting: ================\n{}\n==============", src); let sess = parse::ParseSess::new(FilePathMapping::empty()); let fm = sess.source_map().new_source_file(FileName::Custom("stdin".to_string()), @@ -373,9 +376,9 @@ impl Class { } fn write_header(class: Option<&str>, out: &mut dyn Write) -> io::Result<()> { - write!(out, "
\n", class.unwrap_or(""))
+    write!(out, "
\n", class.unwrap_or(""))
 }
 
 fn write_footer(out: &mut dyn Write) -> io::Result<()> {
-    write!(out, "
\n") + write!(out, "
\n") } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1c61e73fae03c..c83c5d382ddcc 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1709,6 +1709,7 @@ impl<'a> Settings<'a> { ("method-docs", "Auto-hide item methods' documentation", false), ("go-to-only-result", "Directly go to item in search if there is only one result", false), + ("line-numbers", "Show line numbers on code examples", false), ], root_path, suffix, diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 6307dda454da8..9d1a5c3837830 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2093,6 +2093,7 @@ return wrapper; } + var hideItemDeclarations = getCurrentValue('rustdoc-item-declarations') === "false"; onEach(document.getElementsByClassName('docblock'), function(e) { if (hasClass(e, 'autohide')) { var wrap = e.previousElementSibling; @@ -2116,16 +2117,14 @@ } } if (e.parentNode.id === "main") { - var otherMessage; + var otherMessage = ''; var fontSize; var extraClass; - var show = true; if (hasClass(e, "type-decl")) { fontSize = "20px"; otherMessage = ' Show declaration'; - show = getCurrentValue('rustdoc-item-declarations') === "false"; - if (!show) { + if (hideItemDeclarations === false) { extraClass = 'collapsed'; } } else if (hasClass(e, "non-exhaustive")) { @@ -2142,8 +2141,12 @@ extraClass = "marg-left"; } - e.parentNode.insertBefore(createToggle(otherMessage, fontSize, extraClass, show), e); - if (otherMessage && show) { + e.parentNode.insertBefore(createToggle(otherMessage, + fontSize, + extraClass, + hideItemDeclarations), + e); + if (otherMessage.length > 0 && hideItemDeclarations === true) { collapseDocs(e.previousSibling.childNodes[0], "toggle"); } } @@ -2186,13 +2189,33 @@ }); } + // To avoid checking on "rustdoc-item-attributes" value on every loop... + var itemAttributesFunc = function() {}; + if (getCurrentValue("rustdoc-item-attributes") !== "false") { + itemAttributesFunc = function(x) { + collapseDocs(x.previousSibling.childNodes[0], "toggle"); + }; + } onEach(document.getElementById('main').getElementsByClassName('attributes'), function(i_e) { i_e.parentNode.insertBefore(createToggleWrapper(toggle.cloneNode(true)), i_e); - if (getCurrentValue("rustdoc-item-attributes") !== "false") { - collapseDocs(i_e.previousSibling.childNodes[0], "toggle"); - } + itemAttributesFunc(i_e); }); + // To avoid checking on "rustdoc-line-numbers" value on every loop... + var lineNumbersFunc = function() {}; + if (getCurrentValue("rustdoc-line-numbers") === "true") { + lineNumbersFunc = function(x) { + var count = x.textContent.split('\n').length; + var elems = []; + for (var i = 0; i < count; ++i) { + elems.push(i + 1); + } + var node = document.createElement('pre'); + addClass(node, 'line-number'); + node.innerHTML = elems.join('\n'); + x.parentNode.insertBefore(node, x); + }; + } onEach(document.getElementsByClassName('rust-example-rendered'), function(e) { if (hasClass(e, 'compile_fail')) { e.addEventListener("mouseover", function(event) { @@ -2209,6 +2232,7 @@ e.previousElementSibling.childNodes[0].style.color = ''; }); } + lineNumbersFunc(e); }); function showModal(content) { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index ee811f3379239..5817a22574953 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -283,6 +283,24 @@ nav.sub { padding-left: 0; } +.example-wrap { + display: inline-flex; + width: 100%; +} + +.example-wrap > pre.line-number { + overflow: initial; + border: 1px solid; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + padding: 13px 8px; + text-align: right; +} + +.example-wrap > pre.rust { + width: 100%; +} + #search { margin-left: 230px; position: relative; diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 34a1d71beecfc..e179c4586bc74 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -233,6 +233,10 @@ pre.rust .question-mark { color: #ff9011; } +.example-wrap > pre.line-number { + border-color: #4a4949; +} + a.test-arrow { background-color: rgba(78, 139, 202, 0.2); } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 8218b1b371ea7..6ef9875ea2d4d 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -227,6 +227,10 @@ pre.rust .question-mark { color: #ff9011; } +.example-wrap > pre.line-number { + border-color: #c7c7c7; +} + a.test-arrow { background-color: rgba(78, 139, 202, 0.2); } From c514b627e4bea768fe8560b96ce585689d008017 Mon Sep 17 00:00:00 2001 From: Charles Hathaway Date: Wed, 10 Oct 2018 11:13:35 -0400 Subject: [PATCH 20/54] update tcp stream documentation --- src/libstd/net/tcp.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 75c7a3d928094..848570e75e71e 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -44,11 +44,10 @@ use time::Duration; /// use std::net::TcpStream; /// /// { -/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap(); +/// let mut stream = TcpStream::connect("127.0.0.1:34254")?; /// -/// // ignore the Result -/// let _ = stream.write(&[1]); -/// let _ = stream.read(&mut [0; 128]); // ignore here too +/// stream.write(&[1])?; +/// stream.read(&mut [0; 128])?; /// } // the stream is closed here /// ``` #[stable(feature = "rust1", since = "1.0.0")] From c77a0cf5881e8e894d6fc15403cca002b9781d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 10 Oct 2018 16:54:17 -0700 Subject: [PATCH 21/54] Accept `Option>` in macro argument Given the following code, compile successfuly: ``` macro_rules! test { ( fn fun() -> Option>; ) => { fn fun(x: $t) -> Option> { Some(Box::new(x)) } } } test! { fn fun() -> Option>; } ``` --- src/libsyntax/ext/tt/macro_rules.rs | 3 ++- src/test/run-pass/macros/issue-25274.rs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/macros/issue-25274.rs diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 214bc9cffc483..07d9bdb03adc7 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -902,7 +902,8 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result match *tok { TokenTree::Token(_, ref tok) => match *tok { OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) | - Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true), + Comma | FatArrow | Colon | Eq | Gt | BinOp(token::Shr) | Semi | + BinOp(token::Or) => Ok(true), Ident(i, false) if i.name == "as" || i.name == "where" => Ok(true), _ => Ok(false) }, diff --git a/src/test/run-pass/macros/issue-25274.rs b/src/test/run-pass/macros/issue-25274.rs new file mode 100644 index 0000000000000..e81b2c7a7233b --- /dev/null +++ b/src/test/run-pass/macros/issue-25274.rs @@ -0,0 +1,16 @@ +macro_rules! test { + ( + fn fun() -> Option>; + ) => { + fn fun(x: $t) -> Option> + { Some(Box::new(x)) } + } +} + +test! { + fn fun() -> Option>; +} + +fn main() { + println!("{}", fun(0).unwrap()); +} From 4530b8c56cb7c1e539472e09c1e2704f67814912 Mon Sep 17 00:00:00 2001 From: Charles Hathaway Date: Thu, 11 Oct 2018 15:35:48 -0400 Subject: [PATCH 22/54] Small changes to fix documentation auto compile issues --- src/libstd/net/tcp.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 848570e75e71e..ad212a547579b 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -43,11 +43,12 @@ use time::Duration; /// use std::io::prelude::*; /// use std::net::TcpStream; /// -/// { +/// fn main() -> std::io::Result<()> { /// let mut stream = TcpStream::connect("127.0.0.1:34254")?; /// /// stream.write(&[1])?; /// stream.read(&mut [0; 128])?; +/// Ok(()) /// } // the stream is closed here /// ``` #[stable(feature = "rust1", since = "1.0.0")] From f8550a499fcc3c2589ada33dbb3081d77ee968bc Mon Sep 17 00:00:00 2001 From: Son Date: Mon, 20 Aug 2018 12:05:41 +1000 Subject: [PATCH 23/54] Add doc for impl From for Waker --- src/libcore/task/wake.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index ab4ae50c44367..7cc200837b481 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -188,6 +188,13 @@ impl LocalWaker { } impl From for Waker { + /// Converts a [`LocalWaker`] into a [`Waker`]. + /// + /// This conversion forgets local waker and allocates a new waker with + /// the same inner. + /// + /// [`LocalWaker`]: struct.LocalWaker.html + /// [`Waker`]: struct.Waker.html #[inline] fn from(local_waker: LocalWaker) -> Self { local_waker.0 From a70ef6a20bbb9d2ac557e54acccb97e7662550ce Mon Sep 17 00:00:00 2001 From: Son Date: Wed, 17 Oct 2018 08:03:12 +1100 Subject: [PATCH 24/54] Seems like we don't have to refer the file anymore. --- src/libcore/task/wake.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 7cc200837b481..c2768e70aec7b 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -188,13 +188,10 @@ impl LocalWaker { } impl From for Waker { - /// Converts a [`LocalWaker`] into a [`Waker`]. + /// Converts a `LocalWaker` into a `Waker`. /// /// This conversion forgets local waker and allocates a new waker with /// the same inner. - /// - /// [`LocalWaker`]: struct.LocalWaker.html - /// [`Waker`]: struct.Waker.html #[inline] fn from(local_waker: LocalWaker) -> Self { local_waker.0 From 475be10dbd5bef7c37d58f2d5f1905123cb6e19e Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Tue, 16 Oct 2018 21:36:02 -0700 Subject: [PATCH 25/54] in which unused-parens suggestions heed what the user actually wrote MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aaron Hill pointed out that unnecessary parens around a macro call (paradigmatically, `format!`) yielded a suggestion of hideous macro-expanded code. (The slightly unusual choice of using the pretty-printer to compose suggestions was quite recently commented on in the commit message for 1081bbbfc ("abolish ICE when pretty-printing async block"), but without any grounds to condemn it as a 𝘣𝘢𝘥 choice. Hill's report provides the grounds.) `span_to_snippet` is fallable as far as the type system is concerned (because, who knows, macros or something), so the pretty-printing can live on in the oft-neglected `else` branch. Resolves #55109. --- src/librustc_lint/unused.rs | 18 ++++++++++++++---- src/test/ui/lint/suggestions.rs | 4 ++-- src/test/ui/lint/suggestions.stderr | 10 +++++----- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 76717548521b7..e690969732291 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -281,8 +281,13 @@ impl UnusedParens { let necessary = struct_lit_needs_parens && parser::contains_exterior_struct_lit(&inner); if !necessary { - let pattern = pprust::expr_to_string(value); - Self::remove_outer_parens(cx, value.span, &pattern, msg); + let expr_text = if let Ok(snippet) = cx.sess().source_map() + .span_to_snippet(value.span) { + snippet + } else { + pprust::expr_to_string(value) + }; + Self::remove_outer_parens(cx, value.span, &expr_text, msg); } } } @@ -292,8 +297,13 @@ impl UnusedParens { value: &ast::Pat, msg: &str) { if let ast::PatKind::Paren(_) = value.node { - let pattern = pprust::pat_to_string(value); - Self::remove_outer_parens(cx, value.span, &pattern, msg); + let pattern_text = if let Ok(snippet) = cx.sess().source_map() + .span_to_snippet(value.span) { + snippet + } else { + pprust::pat_to_string(value) + }; + Self::remove_outer_parens(cx, value.span, &pattern_text, msg); } } diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs index ff50b3b1ab68f..77d546a00ecd4 100644 --- a/src/test/ui/lint/suggestions.rs +++ b/src/test/ui/lint/suggestions.rs @@ -56,7 +56,7 @@ fn main() { while true { //~^ WARN denote infinite loops //~| HELP use `loop` - let mut a = (1); + let mut registry_no = (format!("NX-{}", 74205)); //~^ WARN does not need to be mutable //~| HELP remove this `mut` //~| WARN unnecessary parentheses @@ -72,6 +72,6 @@ fn main() { //~^ WARN this pattern is redundant //~| HELP remove this } - println!("{} {}", a, b); + println!("{} {}", registry_no, b); } } diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index 340a4a48512e2..73704614815be 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -1,8 +1,8 @@ warning: unnecessary parentheses around assigned value - --> $DIR/suggestions.rs:59:21 + --> $DIR/suggestions.rs:59:31 | -LL | let mut a = (1); - | ^^^ help: remove these parentheses +LL | let mut registry_no = (format!("NX-{}", 74205)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses | note: lint level defined here --> $DIR/suggestions.rs:13:21 @@ -21,8 +21,8 @@ LL | #[no_debug] // should suggest removal of deprecated attribute warning: variable does not need to be mutable --> $DIR/suggestions.rs:59:13 | -LL | let mut a = (1); - | ----^ +LL | let mut registry_no = (format!("NX-{}", 74205)); + | ----^^^^^^^^^^^ | | | help: remove this `mut` | From 655f9d8e2183c71e957c4cb43e4819bad4d3d037 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 20 Oct 2018 14:45:08 +0200 Subject: [PATCH 26/54] Move cg_llvm::back::linker to cg_utils --- src/Cargo.lock | 2 + src/librustc_codegen_llvm/back/archive.rs | 24 +--------- src/librustc_codegen_llvm/back/link.rs | 7 +-- src/librustc_codegen_llvm/back/lto.rs | 2 +- src/librustc_codegen_llvm/back/write.rs | 6 +-- src/librustc_codegen_llvm/lib.rs | 30 ++---------- src/librustc_codegen_utils/Cargo.toml | 2 + .../command.rs | 0 src/librustc_codegen_utils/lib.rs | 47 +++++++++++++++++++ .../back => librustc_codegen_utils}/linker.rs | 27 ++++++----- .../symbol_export.rs | 2 +- 11 files changed, 82 insertions(+), 67 deletions(-) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/command.rs (100%) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/linker.rs (98%) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/symbol_export.rs (99%) diff --git a/src/Cargo.lock b/src/Cargo.lock index 52314b0ac8998..c1dc24ee2425d 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2137,11 +2137,13 @@ dependencies = [ "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc_allocator 0.0.0", "rustc_data_structures 0.0.0", "rustc_incremental 0.0.0", "rustc_metadata_utils 0.0.0", "rustc_mir 0.0.0", "rustc_target 0.0.0", + "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index af9efc6d7c417..ce4cb1ea3a042 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -52,28 +52,6 @@ enum Addition { }, } -pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session) - -> PathBuf { - // On Windows, static libraries sometimes show up as libfoo.a and other - // times show up as foo.lib - let oslibname = format!("{}{}{}", - sess.target.target.options.staticlib_prefix, - name, - sess.target.target.options.staticlib_suffix); - let unixlibname = format!("lib{}.a", name); - - for path in search_paths { - debug!("looking for {} inside {:?}", name, path); - let test = path.join(&oslibname); - if test.exists() { return test } - if oslibname != unixlibname { - let test = path.join(&unixlibname); - if test.exists() { return test } - } - } - sess.fatal(&format!("could not find native static library `{}`, \ - perhaps an -L flag is missing?", name)); -} fn is_relevant_child(c: &Child) -> bool { match c.name() { @@ -128,7 +106,7 @@ impl<'a> ArchiveBuilder<'a> { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. pub fn add_native_library(&mut self, name: &str) { - let location = find_library(name, &self.config.lib_search_paths, + let location = ::rustc_codegen_utils::find_library(name, &self.config.lib_search_paths, self.config.sess); self.add_archive(&location, |_| false).unwrap_or_else(|e| { self.config.sess.fatal(&format!("failed to add native library {}: {}", diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 9fac343b846e4..34679368f2625 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -12,8 +12,6 @@ use back::wasm; use cc::windows_registry; use super::archive::{ArchiveBuilder, ArchiveConfig}; use super::bytecode::RLIB_BYTECODE_EXTENSION; -use super::linker::Linker; -use super::command::Command; use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; @@ -31,6 +29,8 @@ use rustc::hir::def_id::CrateNum; use tempfile::{Builder as TempFileBuilder, TempDir}; use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor}; use rustc_data_structures::fx::FxHashSet; +use rustc_codegen_utils::linker::Linker; +use rustc_codegen_utils::command::Command; use context::get_reloc_model; use llvm; @@ -701,7 +701,8 @@ fn link_natively(sess: &Session, } { - let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor); + let target_cpu = ::llvm_util::target_cpu(sess); + let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu); link_args(&mut *linker, flavor, sess, crate_type, tmpdir, out_filename, codegen_results); cmd = linker.finalize(); diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 3ac22f4eaef65..69204715f370f 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -9,7 +9,6 @@ // except according to those terms. use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION}; -use back::symbol_export; use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; use back::write::{self, DiagnosticHandlers, pre_lto_bitcode_filename}; use errors::{FatalError, Handler}; @@ -24,6 +23,7 @@ use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::session::config::{self, Lto}; use rustc::util::common::time_ext; use rustc_data_structures::fx::FxHashMap; +use rustc_codegen_utils::symbol_export; use time_graph::Timeline; use {ModuleCodegen, ModuleLlvm, ModuleKind}; diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 02ef690b94233..cc4a3d2a85165 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -12,9 +12,6 @@ use attributes; use back::bytecode::{self, RLIB_BYTECODE_EXTENSION}; use back::lto::{self, ModuleBuffer, ThinBuffer, SerializedModule}; use back::link::{self, get_linker, remove}; -use back::command::Command; -use back::linker::LinkerInfo; -use back::symbol_export::ExportedSymbols; use base; use consts; use memmap; @@ -38,6 +35,9 @@ use rustc::util::common::{time_ext, time_depth, set_time_depth, print_time_passe use rustc_fs_util::{path2cstr, link_or_copy}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::svh::Svh; +use rustc_codegen_utils::command::Command; +use rustc_codegen_utils::linker::LinkerInfo; +use rustc_codegen_utils::symbol_export::ExportedSymbols; use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId}; use errors::emitter::{Emitter}; use syntax::attr; diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 63a8ab077e5ae..f64cf0c7364dd 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -71,7 +71,6 @@ use back::bytecode::RLIB_BYTECODE_EXTENSION; pub use llvm_util::target_features; use std::any::Any; -use std::path::{PathBuf}; use std::sync::mpsc; use rustc_data_structures::sync::Lrc; @@ -87,20 +86,17 @@ use rustc::util::time_graph; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::util::profiling::ProfileCategory; use rustc_mir::monomorphize; +use rustc_codegen_utils::{CompiledModule, ModuleKind}; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::svh::Svh; mod diagnostics; mod back { - pub use rustc_codegen_utils::symbol_names; mod archive; pub mod bytecode; - mod command; - pub mod linker; pub mod link; pub mod lto; - pub mod symbol_export; pub mod write; mod rpath; pub mod wasm; @@ -194,14 +190,14 @@ impl CodegenBackend for LlvmCodegenBackend { } fn provide(&self, providers: &mut ty::query::Providers) { - back::symbol_names::provide(providers); - back::symbol_export::provide(providers); + rustc_codegen_utils::symbol_export::provide(providers); + rustc_codegen_utils::symbol_names::provide(providers); base::provide(providers); attributes::provide(providers); } fn provide_extern(&self, providers: &mut ty::query::Providers) { - back::symbol_export::provide_extern(providers); + rustc_codegen_utils::symbol_export::provide_extern(providers); base::provide_extern(providers); attributes::provide_extern(providers); } @@ -281,13 +277,6 @@ struct CachedModuleCodegen { source: WorkProduct, } -#[derive(Copy, Clone, Debug, PartialEq)] -enum ModuleKind { - Regular, - Metadata, - Allocator, -} - impl ModuleCodegen { fn into_compiled_module(self, emit_obj: bool, @@ -321,15 +310,6 @@ impl ModuleCodegen { } } -#[derive(Debug)] -struct CompiledModule { - name: String, - kind: ModuleKind, - object: Option, - bytecode: Option, - bytecode_compressed: Option, -} - struct ModuleLlvm { llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, @@ -377,7 +357,7 @@ struct CodegenResults { crate_hash: Svh, metadata: rustc::middle::cstore::EncodedMetadata, windows_subsystem: Option, - linker_info: back::linker::LinkerInfo, + linker_info: rustc_codegen_utils::linker::LinkerInfo, crate_info: CrateInfo, } diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index a1f4a323f849e..3a09e8e4b5606 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -13,9 +13,11 @@ test = false flate2 = "1.0" log = "0.4" +serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } rustc = { path = "../librustc" } +rustc_allocator = { path = "../librustc_allocator" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_mir = { path = "../librustc_mir" } diff --git a/src/librustc_codegen_llvm/back/command.rs b/src/librustc_codegen_utils/command.rs similarity index 100% rename from src/librustc_codegen_llvm/back/command.rs rename to src/librustc_codegen_utils/command.rs diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 03b3b20a4e772..89cf19d047216 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -30,8 +30,10 @@ extern crate flate2; #[macro_use] extern crate log; +extern crate serialize; #[macro_use] extern crate rustc; +extern crate rustc_allocator; extern crate rustc_target; extern crate rustc_mir; extern crate rustc_incremental; @@ -40,10 +42,16 @@ extern crate syntax_pos; #[macro_use] extern crate rustc_data_structures; extern crate rustc_metadata_utils; +use std::path::PathBuf; + +use rustc::session::Session; use rustc::ty::TyCtxt; +pub mod command; pub mod link; +pub mod linker; pub mod codegen_backend; +pub mod symbol_export; pub mod symbol_names; pub mod symbol_names_test; @@ -61,4 +69,43 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) { } } +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ModuleKind { + Regular, + Metadata, + Allocator, +} + +#[derive(Debug)] +pub struct CompiledModule { + pub name: String, + pub kind: ModuleKind, + pub object: Option, + pub bytecode: Option, + pub bytecode_compressed: Option, +} + +pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session) + -> PathBuf { + // On Windows, static libraries sometimes show up as libfoo.a and other + // times show up as foo.lib + let oslibname = format!("{}{}{}", + sess.target.target.options.staticlib_prefix, + name, + sess.target.target.options.staticlib_suffix); + let unixlibname = format!("lib{}.a", name); + + for path in search_paths { + debug!("looking for {} inside {:?}", name, path); + let test = path.join(&oslibname); + if test.exists() { return test } + if oslibname != unixlibname { + let test = path.join(&unixlibname); + if test.exists() { return test } + } + } + sess.fatal(&format!("could not find native static library `{}`, \ + perhaps an -L flag is missing?", name)); +} + __build_diagnostic_array! { librustc_codegen_utils, DIAGNOSTICS } diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_utils/linker.rs similarity index 98% rename from src/librustc_codegen_llvm/back/linker.rs rename to src/librustc_codegen_utils/linker.rs index e18c8b9dec463..c1f41fd509a14 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_utils/linker.rs @@ -15,9 +15,7 @@ use std::io::prelude::*; use std::io::{self, BufWriter}; use std::path::{Path, PathBuf}; -use back::archive; -use back::command::Command; -use back::symbol_export; +use command::Command; use rustc::hir::def_id::{LOCAL_CRATE, CrateNum}; use rustc::middle::dependency_format::Linkage; use rustc::session::Session; @@ -26,7 +24,6 @@ use rustc::session::config::{self, CrateType, OptLevel, DebugInfo, use rustc::ty::TyCtxt; use rustc_target::spec::{LinkerFlavor, LldFlavor}; use serialize::{json, Encoder}; -use llvm_util; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. @@ -43,10 +40,13 @@ impl LinkerInfo { } } - pub fn to_linker<'a>(&'a self, - cmd: Command, - sess: &'a Session, - flavor: LinkerFlavor) -> Box { + pub fn to_linker<'a>( + &'a self, + cmd: Command, + sess: &'a Session, + flavor: LinkerFlavor, + target_cpu: &'a str, + ) -> Box { match flavor { LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { @@ -70,6 +70,7 @@ impl LinkerInfo { info: self, hinted_static: false, is_ld: false, + target_cpu, }) as Box } @@ -82,6 +83,7 @@ impl LinkerInfo { info: self, hinted_static: false, is_ld: true, + target_cpu, }) as Box } @@ -144,6 +146,7 @@ pub struct GccLinker<'a> { hinted_static: bool, // Keeps track of the current hinting mode. // Link as ld is_ld: bool, + target_cpu: &'a str, } impl<'a> GccLinker<'a> { @@ -204,7 +207,8 @@ impl<'a> GccLinker<'a> { }; self.linker_arg(&format!("-plugin-opt={}", opt_level)); - self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess))); + let target_cpu = self.target_cpu; + self.linker_arg(&format!("-plugin-opt=mcpu={}", target_cpu)); match self.sess.lto() { config::Lto::Thin | @@ -263,7 +267,7 @@ impl<'a> Linker for GccLinker<'a> { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = archive::find_library(lib, search_path, &self.sess); + let lib = ::find_library(lib, search_path, &self.sess); self.linker_arg(&lib); } } @@ -898,7 +902,8 @@ impl<'a> Linker for EmLinker<'a> { fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { let mut symbols = Vec::new(); - let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); + let export_threshold = + ::symbol_export::crates_export_threshold(&[crate_type]); for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { if level.is_below_threshold(export_threshold) { symbols.push(symbol.symbol_name(tcx).to_string()); diff --git a/src/librustc_codegen_llvm/back/symbol_export.rs b/src/librustc_codegen_utils/symbol_export.rs similarity index 99% rename from src/librustc_codegen_llvm/back/symbol_export.rs rename to src/librustc_codegen_utils/symbol_export.rs index 6b1b0b94fd9d7..2d650f7f18d6f 100644 --- a/src/librustc_codegen_llvm/back/symbol_export.rs +++ b/src/librustc_codegen_utils/symbol_export.rs @@ -11,7 +11,7 @@ use rustc_data_structures::sync::Lrc; use std::sync::Arc; -use monomorphize::Instance; +use rustc::ty::Instance; use rustc::hir; use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; From 9378705f8232536cf12f8b38cea8757599d65cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Oct 2018 17:53:12 +0200 Subject: [PATCH 27/54] submodules: update clippy from 5afdf8b7 to b1d03437 Changes: ```` new_ret_no_self: add sample from #3313 to Known Problems section. Support multiline comments and hopefully fix panic Check for comments in collapsible ifs Resolve ICE in needless range loop lint RIIR update_lints: Update changelog links Rename if_let_redundant_pattern_matching to redundant_pattern_matching Add lint for redundant pattern matching for explicit return boolean Fix issue #3322: reword help message for len_zero Simplify manual_memcpy suggestion in some cases Fix dogfood Update known problems for unnecessary_fold RIIR update_lints: Replace lint count in README.md Rename `active_lints` to `usable_lints` Add comment on WalkDir vs. fs::read_dir sort_by -> sort_by_key Some more documentation for clippy_dev Use `WalkDir` to also gather from subdirectories Avoid linting `boxed_local` on trait implementations. Website: Make lint categories linkable Restore clippy_dummy's placeholder name Swap order of methods in `needless_range_loop` suggestion in some cases Revert "Exclude pattern guards from unnecessary_fold lint" Exclude pattern guards from unnecessary_fold lint ```` --- src/Cargo.lock | 1 + src/tools/clippy | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 3361e81ecfe6d..dd21108352792 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -349,6 +349,7 @@ dependencies = [ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/src/tools/clippy b/src/tools/clippy index 5afdf8b78507d..b1d0343749bdc 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 5afdf8b78507ddf015d192858aef56e72c17de16 +Subproject commit b1d0343749bdc87e5cbbe7f1aeaa9d2a2c9dbc5b From 0f6e2741f692add6d1995b630e2073d18aa2b2ba Mon Sep 17 00:00:00 2001 From: Peter Hall Date: Sun, 21 Oct 2018 18:53:09 +0100 Subject: [PATCH 28/54] Clarified code example The example was not as clear as it could be because it was making an assumption about the structure of the data in order to multiply the number of collection elements by the item size. This change demonstrates the idea more straightforwardly, without the calculation. --- src/libstd/primitive_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 7074928eaf6da..79ccd5939148b 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -322,8 +322,8 @@ mod prim_never { } /// let s = String::from("love: ❤️"); /// let v: Vec = s.chars().collect(); /// -/// assert_eq!(12, s.len() * std::mem::size_of::()); -/// assert_eq!(32, v.len() * std::mem::size_of::()); +/// assert_eq!(12, std::mem::size_of_val(&s[..])); +/// assert_eq!(32, std::mem::size_of_val(&v[..])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] mod prim_char { } From 9f7009628fcfdd6ba6bb8e8effb27abcac1cf13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=85dzio=C5=82ka?= Date: Sun, 21 Oct 2018 23:42:19 +0200 Subject: [PATCH 29/54] Fix a typo in the documentation of RangeInclusive --- src/libcore/ops/range.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 07ba285ea5cb3..fd3e50998fe8c 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -304,7 +304,7 @@ impl> RangeTo { } } -/// An range bounded inclusively below and above (`start..=end`). +/// A range bounded inclusively below and above (`start..=end`). /// /// The `RangeInclusive` `start..=end` contains all values with `x >= start` /// and `x <= end`. It is empty unless `start <= end`. From b0d3d3b959e34ecb6c0b7c29f22c77d8c301514d Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sun, 21 Oct 2018 15:37:01 -0700 Subject: [PATCH 30/54] only issue "variant of the expected type" suggestion for enums Felix S. Klock II pointed out that this suggestion (introduced in pull-request #43178 / eac74104) was being issued for one-field-struct expected types (in which case it is misleading and outright wrong), even though it was only intended for one-field enum-variants (most notably, `Some`). Particularly tender-hearted code-historians may be inclined to show mercy towards the author of #43178 on the grounds that it's somewhat confusing that struct field definitions are given in a type called `ty::VariantDef`. Add a conditional to adhere to the original intent. (It would be possible to generalize to structs, but not obviously net desirable.) This adds a level of indentation, so the diff here is going to be easier to read in ignore-whitespace mode (`-w`). Resolves #55250. --- src/librustc_typeck/check/demand.rs | 53 +++++++++++---------- src/test/ui/did_you_mean/issue-42764.rs | 16 +++++++ src/test/ui/did_you_mean/issue-42764.stderr | 11 ++++- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index d82d36a1937bf..7773e2d570844 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -111,34 +111,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expr_ty = self.resolve_type_vars_with_obligations(checked_ty); let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); - // If the expected type is an enum with any variants whose sole - // field is of the found type, suggest such variants. See Issue - // #42764. + // If the expected type is an enum (Issue #55250) with any variants whose + // sole field is of the found type, suggest such variants. (Issue #42764) if let ty::Adt(expected_adt, substs) = expected.sty { - let mut compatible_variants = expected_adt.variants - .iter() - .filter(|variant| variant.fields.len() == 1) - .filter_map(|variant| { - let sole_field = &variant.fields[0]; - let sole_field_ty = sole_field.ty(self.tcx, substs); - if self.can_coerce(expr_ty, sole_field_ty) { - let variant_path = self.tcx.item_path_str(variant.did); - Some(variant_path.trim_left_matches("std::prelude::v1::").to_string()) - } else { - None + if expected_adt.is_enum() { + let mut compatible_variants = expected_adt.variants + .iter() + .filter(|variant| variant.fields.len() == 1) + .filter_map(|variant| { + let sole_field = &variant.fields[0]; + let sole_field_ty = sole_field.ty(self.tcx, substs); + if self.can_coerce(expr_ty, sole_field_ty) { + let variant_path = self.tcx.item_path_str(variant.did); + Some(variant_path.trim_left_matches("std::prelude::v1::").to_string()) + } else { + None + } + }).peekable(); + + if compatible_variants.peek().is_some() { + let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr)); + let suggestions = compatible_variants + .map(|v| format!("{}({})", v, expr_text)).collect::>(); + err.span_suggestions_with_applicability( + expr.span, + "try using a variant of the expected type", + suggestions, + Applicability::MaybeIncorrect, + ); } - }).peekable(); - - if compatible_variants.peek().is_some() { - let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr)); - let suggestions = compatible_variants.map(|v| - format!("{}({})", v, expr_text)).collect::>(); - err.span_suggestions_with_applicability( - expr.span, - "try using a variant of the expected type", - suggestions, - Applicability::MaybeIncorrect, - ); } } diff --git a/src/test/ui/did_you_mean/issue-42764.rs b/src/test/ui/did_you_mean/issue-42764.rs index ff4bb428d5f5f..1c79499ba5902 100644 --- a/src/test/ui/did_you_mean/issue-42764.rs +++ b/src/test/ui/did_you_mean/issue-42764.rs @@ -20,4 +20,20 @@ fn main() { let n: usize = 42; this_function_expects_a_double_option(n); //~^ ERROR mismatched types + //~| HELP try using a variant of the expected type +} + + +// But don't issue the "try using a variant" help if the one-"variant" ADT is +// actually a one-field struct. + +struct Payload; + +struct Wrapper { payload: Payload } + +struct Context { wrapper: Wrapper } + +fn overton() { + let _c = Context { wrapper: Payload{} }; + //~^ ERROR mismatched types } diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr index f1da920872d7c..e256a436affba 100644 --- a/src/test/ui/did_you_mean/issue-42764.stderr +++ b/src/test/ui/did_you_mean/issue-42764.stderr @@ -13,6 +13,15 @@ LL | this_function_expects_a_double_option(DoubleOption::FirstSome(n)); LL | this_function_expects_a_double_option(DoubleOption::AlternativeSome(n)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-42764.rs:37:33 + | +LL | let _c = Context { wrapper: Payload{} }; + | ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload` + | + = note: expected type `Wrapper` + found type `Payload` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. From c675111095244f4430fd1c15b2de53c9e5281cb0 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 22 Oct 2018 00:31:07 +0100 Subject: [PATCH 31/54] Correct trailing ellipsis in name_from_pat --- src/librustdoc/clean/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index db605e57735aa..2e6cc4bd54c61 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3632,7 +3632,7 @@ fn name_from_pat(p: &hir::Pat) -> String { fields.iter().map(|&Spanned { node: ref fp, .. }| format!("{}: {}", fp.ident, name_from_pat(&*fp.pat))) .collect::>().join(", "), - if etc { ", ..." } else { "" } + if etc { ", .." } else { "" } ) } PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) From 412ad9bf3746bd0682db136c36a433f3205715f1 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Sun, 21 Oct 2018 20:09:42 -0700 Subject: [PATCH 32/54] Allow extern statics with an extern type Fixes #55239 --- src/librustc_typeck/check/wfcheck.rs | 42 +++++++++++++++--------- src/test/ui/static/static-extern-type.rs | 37 +++++++++++++++++++++ 2 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/static/static-extern-type.rs diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ec773e384af38..ec6ca242fa36b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -13,7 +13,7 @@ use constrained_type_params::{identify_constrained_type_params, Parameter}; use hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; -use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; +use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; @@ -119,14 +119,14 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def check_item_fn(tcx, item); } hir::ItemKind::Static(ref ty, ..) => { - check_item_type(tcx, item.id, ty.span); + check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::Const(ref ty, ..) => { - check_item_type(tcx, item.id, ty.span); + check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::ForeignMod(ref module) => for it in module.items.iter() { if let hir::ForeignItemKind::Static(ref ty, ..) = it.node { - check_item_type(tcx, it.id, ty.span); + check_item_type(tcx, it.id, ty.span, true); } }, hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { @@ -340,23 +340,35 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { }) } -fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId, ty_span: Span) { +fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + ty_span: Span, + allow_foreign_ty: bool) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| { let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); - fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); - fcx.register_bound( - item_ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new( - ty_span, - fcx.body_id, - traits::MiscObligation, - ), - ); + let mut allow_unsized = false; + if allow_foreign_ty { + if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty { + allow_unsized = true; + } + } + + if !allow_unsized { + fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + fcx.register_bound( + item_ty, + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + traits::ObligationCause::new( + ty_span, + fcx.body_id, + traits::MiscObligation, + ), + ); + } vec![] // no implied bounds in a const etc }); diff --git a/src/test/ui/static/static-extern-type.rs b/src/test/ui/static/static-extern-type.rs new file mode 100644 index 0000000000000..72e2853b9f038 --- /dev/null +++ b/src/test/ui/static/static-extern-type.rs @@ -0,0 +1,37 @@ +// Copyright 2018 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-pass +#![feature(extern_types)] + +pub mod a { + extern "C" { + pub type StartFn; + pub static start: StartFn; + } +} + +pub mod b { + #[repr(transparent)] + pub struct TransparentType(::a::StartFn); + extern "C" { + pub static start: TransparentType; + } +} + +pub mod c { + #[repr(C)] + pub struct CType(u32, ::b::TransparentType); + extern "C" { + pub static start: CType; + } +} + +fn main() {} From 9f0a352999bfe4f265d6930a49efee7b80fe6ef5 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 22 Oct 2018 15:45:03 +0200 Subject: [PATCH 33/54] Turn ICE for dangling pointers into error --- src/librustc_mir/interpret/memory.rs | 5 +++++ src/test/ui/consts/dangling-alloc-id-ice.rs | 15 +++++++++++++++ src/test/ui/consts/dangling-alloc-id-ice.stderr | 13 +++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/test/ui/consts/dangling-alloc-id-ice.rs create mode 100644 src/test/ui/consts/dangling-alloc-id-ice.stderr diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 9adca6c429798..954616fe9fcd7 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -732,6 +732,11 @@ where if self.alloc_map.contains_key(&alloc) { // Not yet interned, so proceed recursively self.intern_static(alloc, mutability)?; + } else if self.dead_alloc_map.contains_key(&alloc) { + // danging pointer + return err!(ValidationFailure( + "encountered dangling pointer in final constant".into(), + )) } } Ok(()) diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs new file mode 100644 index 0000000000000..31fa23ae23221 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice.rs @@ -0,0 +1,15 @@ +// https://github.com/rust-lang/rust/issues/55223 + +#![feature(const_let)] + +union Foo<'a> { + y: &'a (), + long_live_the_unit: &'static (), +} + +const FOO: &() = { //~ ERROR this constant cannot be used + let y = (); + unsafe { Foo { y: &y }.long_live_the_unit } +}; + +fn main() {} diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr new file mode 100644 index 0000000000000..df623f943addc --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -0,0 +1,13 @@ +error: this constant cannot be used + --> $DIR/dangling-alloc-id-ice.rs:10:1 + | +LL | / const FOO: &() = { //~ ERROR this constant cannot be used +LL | | let y = (); +LL | | unsafe { Foo { y: &y }.long_live_the_unit } +LL | | }; + | |__^ type validation failed: encountered dangling pointer in final constant + | + = note: #[deny(const_err)] on by default + +error: aborting due to previous error + From 5b84550d7c39821704a48b53c8cbe3916ab100b7 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Mon, 22 Oct 2018 07:03:53 -0700 Subject: [PATCH 34/54] Keep an obligation for both sized and unsized types --- src/librustc_typeck/check/wfcheck.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ec6ca242fa36b..f21296a2a0772 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -340,33 +340,31 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { }) } -fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - ty_span: Span, - allow_foreign_ty: bool) { +fn check_item_type<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + ty_span: Span, + allow_foreign_ty: bool, +) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| { let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); - let mut allow_unsized = false; + let mut forbid_unsized = true; if allow_foreign_ty { if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty { - allow_unsized = true; + forbid_unsized = false; } } - if !allow_unsized { - fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + if forbid_unsized { fcx.register_bound( item_ty, fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new( - ty_span, - fcx.body_id, - traits::MiscObligation, - ), + traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation), ); } From 0ba126217d4d349e5d9681bbb838c036adb55d18 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 22 Oct 2018 18:05:27 +0200 Subject: [PATCH 35/54] Reproduce the underlying issue nll (and thus the algorithm for actual promotion) don't know about some casts anymore --- .../consts/dangling-alloc-id-ice-2.nll.stderr | 30 +++++++++++++++++++ src/test/ui/consts/dangling-alloc-id-ice-2.rs | 10 +++++++ .../ui/consts/dangling-alloc-id-ice-2.stderr | 11 +++++++ 3 files changed, 51 insertions(+) create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.rs create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.stderr diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr b/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr new file mode 100644 index 0000000000000..e6ae57796055f --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr @@ -0,0 +1,30 @@ +warning[E0716]: temporary value dropped while borrowed + --> $DIR/dangling-alloc-id-ice-2.rs:5:28 + | +LL | static MAP: Slice = Slice(&[ + | ___________________________-^ + | |___________________________| + | || +LL | || b"CloseEvent" as &'static [u8], +LL | || ]); + | || -- temporary value is freed at the end of this statement + | ||_| + | |__creates a temporary which is freed while still in use + | cast requires that borrow lasts for `'static` + | + = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. + It represents potential unsoundness in your code. + This warning will become a hard error in the future. + +error[E0080]: could not evaluate static initializer + --> $DIR/dangling-alloc-id-ice-2.rs:5:1 + | +LL | / static MAP: Slice = Slice(&[ +LL | | b"CloseEvent" as &'static [u8], +LL | | ]); + | |___^ type validation failed: encountered dangling pointer in final constant + +error: aborting due to previous error + +Some errors occurred: E0080, E0716. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.rs b/src/test/ui/consts/dangling-alloc-id-ice-2.rs new file mode 100644 index 0000000000000..9af72c8dc0b83 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.rs @@ -0,0 +1,10 @@ +// https://github.com/rust-lang/rust/issues/55223 + +struct Slice(&'static [&'static [u8]]); + +static MAP: Slice = Slice(&[ + b"CloseEvent" as &'static [u8], +]); + + +fn main() {} diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.stderr b/src/test/ui/consts/dangling-alloc-id-ice-2.stderr new file mode 100644 index 0000000000000..42df542f55cf5 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.stderr @@ -0,0 +1,11 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/dangling-alloc-id-ice-2.rs:5:1 + | +LL | / static MAP: Slice = Slice(&[ +LL | | b"CloseEvent" as &'static [u8], +LL | | ]); + | |___^ type validation failed: encountered dangling pointer in final constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 80a6b736acca2c109547e100d217fe5ca5f4ec30 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 23 Oct 2018 01:54:02 +0900 Subject: [PATCH 36/54] Unimplement ExactSizeIterator If root is not START_BLOCK, `basic_blocks().len() - visited` does not represent their exact size. --- src/librustc/mir/traversal.rs | 36 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index db1bc3e7519c2..a1e2b7a06468d 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -34,6 +34,7 @@ pub struct Preorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, visited: BitSet, worklist: Vec, + root_is_start_block: bool, } impl<'a, 'tcx> Preorder<'a, 'tcx> { @@ -44,6 +45,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { mir, visited: BitSet::new_empty(mir.basic_blocks().len()), worklist, + root_is_start_block: root == START_BLOCK, } } } @@ -75,15 +77,19 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { fn size_hint(&self) -> (usize, Option) { // All the blocks, minus the number of blocks we've visited. - let remaining = self.mir.basic_blocks().len() - self.visited.count(); + let upper = self.mir.basic_blocks().len() - self.visited.count(); - // We will visit all remaining blocks exactly once. - (remaining, Some(remaining)) + let lower = if self.root_is_start_block { + // We will visit all remaining blocks exactly once. + upper + } else { + self.worklist.len() + }; + + (lower, Some(upper)) } } -impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} - /// Postorder traversal of a graph. /// /// Postorder traversal is when each node is visited after all of it's @@ -105,7 +111,8 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} pub struct Postorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, visited: BitSet, - visit_stack: Vec<(BasicBlock, Successors<'a>)> + visit_stack: Vec<(BasicBlock, Successors<'a>)>, + root_is_start_block: bool, } impl<'a, 'tcx> Postorder<'a, 'tcx> { @@ -113,7 +120,8 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { let mut po = Postorder { mir, visited: BitSet::new_empty(mir.basic_blocks().len()), - visit_stack: Vec::new() + visit_stack: Vec::new(), + root_is_start_block: root == START_BLOCK, }; @@ -214,15 +222,19 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { fn size_hint(&self) -> (usize, Option) { // All the blocks, minus the number of blocks we've visited. - let remaining = self.mir.basic_blocks().len() - self.visited.count(); + let upper = self.mir.basic_blocks().len() - self.visited.count(); - // We will visit all remaining blocks exactly once. - (remaining, Some(remaining)) + let lower = if self.root_is_start_block { + // We will visit all remaining blocks exactly once. + upper + } else { + self.visit_stack.len() + }; + + (lower, Some(upper)) } } -impl<'a, 'tcx> ExactSizeIterator for Postorder<'a, 'tcx> {} - /// Reverse postorder traversal of a graph /// /// Reverse postorder is the reverse order of a postorder traversal. From b5336c0b9755f635db4eafba6254e192ee451e6a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Oct 2018 09:11:11 +1100 Subject: [PATCH 37/54] Add a cheap mode for `compute_missing_ctors`. `compute_missing_ctors` is called a lot. It produces a vector, which can be reasonably large (e.g. 100+ elements), but the vector is almost always only checked for emptiness. This commit changes `compute_missing_ctors` so it can be called in a cheap way that just indicates if the vector would be empty. If necessary, the function can subsequently be called in an expensive way to compute the full vector. This change reduces instruction counts for several benchmarks up to 2%. --- src/librustc_mir/hair/pattern/_match.rs | 85 +++++++++++++++++++------ 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index aa1c6902dce33..7f46e2f384551 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -931,12 +931,37 @@ impl<'tcx> IntRange<'tcx> { } } -// Return a set of constructors equivalent to `all_ctors \ used_ctors`. +// A request for missing constructor data in terms of either: +// - whether or not there any missing constructors; or +// - the actual set of missing constructors. +#[derive(PartialEq)] +enum MissingCtorsInfo { + Emptiness, + Ctors, +} + +// Used by `compute_missing_ctors`. +#[derive(Debug, PartialEq)] +enum MissingCtors<'tcx> { + Empty, + NonEmpty, + + // Note that the Vec can be empty. + Ctors(Vec>), +} + +// When `info` is `MissingCtorsInfo::Ctors`, compute a set of constructors +// equivalent to `all_ctors \ used_ctors`. When `info` is +// `MissingCtorsInfo::Emptiness`, just determines if that set is empty or not. +// (The split logic gives a performance win, because we always need to know if +// the set is empty, but we rarely need the full set, and it can be expensive +// to compute the full set.) fn compute_missing_ctors<'a, 'tcx: 'a>( + info: MissingCtorsInfo, tcx: TyCtxt<'a, 'tcx, 'tcx>, all_ctors: &Vec>, used_ctors: &Vec>, -) -> Vec> { +) -> MissingCtors<'tcx> { let mut missing_ctors = vec![]; for req_ctor in all_ctors { @@ -965,10 +990,22 @@ fn compute_missing_ctors<'a, 'tcx: 'a>( // We add `refined_ctors` instead of `req_ctor`, because then we can // provide more detailed error information about precisely which // ranges have been omitted. - missing_ctors.extend(refined_ctors); + if info == MissingCtorsInfo::Emptiness { + if !refined_ctors.is_empty() { + // The set is non-empty; return early. + return MissingCtors::NonEmpty; + } + } else { + missing_ctors.extend(refined_ctors); + } } - missing_ctors + if info == MissingCtorsInfo::Emptiness { + // If we reached here, the set is empty. + MissingCtors::Empty + } else { + MissingCtors::Ctors(missing_ctors) + } } /// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html @@ -1081,20 +1118,23 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // feature flag is not present, so this is only // needed for that case. - // Find those constructors that are not matched by any non-wildcard patterns in the - // current column. - let missing_ctors = compute_missing_ctors(cx.tcx, &all_ctors, &used_ctors); + // Missing constructors are those that are not matched by any + // non-wildcard patterns in the current column. We always determine if + // the set is empty, but we only fully construct them on-demand, + // because they're rarely used and can be big. + let cheap_missing_ctors = + compute_missing_ctors(MissingCtorsInfo::Emptiness, cx.tcx, &all_ctors, &used_ctors); let is_privately_empty = all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty); let is_declared_nonexhaustive = cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty); - debug!("missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}", - missing_ctors, is_privately_empty, is_declared_nonexhaustive); + debug!("cheap_missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}", + cheap_missing_ctors, is_privately_empty, is_declared_nonexhaustive); // For privately empty and non-exhaustive enums, we work as if there were an "extra" // `_` constructor for the type, so we can never match over all constructors. let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive; - if missing_ctors.is_empty() && !is_non_exhaustive { + if cheap_missing_ctors == MissingCtors::Empty && !is_non_exhaustive { split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| { is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) }).find(|result| result.is_useful()).unwrap_or(NotUseful) @@ -1165,15 +1205,22 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, witness }).collect() } else { - pats.into_iter().flat_map(|witness| { - missing_ctors.iter().map(move |ctor| { - // Extends the witness with a "wild" version of this - // constructor, that matches everything that can be built with - // it. For example, if `ctor` is a `Constructor::Variant` for - // `Option::Some`, this pushes the witness for `Some(_)`. - witness.clone().push_wild_constructor(cx, ctor, pcx.ty) - }) - }).collect() + let expensive_missing_ctors = + compute_missing_ctors(MissingCtorsInfo::Ctors, cx.tcx, &all_ctors, + &used_ctors); + if let MissingCtors::Ctors(missing_ctors) = expensive_missing_ctors { + pats.into_iter().flat_map(|witness| { + missing_ctors.iter().map(move |ctor| { + // Extends the witness with a "wild" version of this + // constructor, that matches everything that can be built with + // it. For example, if `ctor` is a `Constructor::Variant` for + // `Option::Some`, this pushes the witness for `Some(_)`. + witness.clone().push_wild_constructor(cx, ctor, pcx.ty) + }) + }).collect() + } else { + bug!("cheap missing ctors") + } }; UsefulWithWitness(new_witnesses) } From e1e52eb5a0156839a71c0ffc5424e2160271170e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 17 Oct 2018 21:07:31 -0700 Subject: [PATCH 38/54] Suggest appropriate syntax on missing lifetime specifier in return type Suggest using `'static` when a lifetime is missing in the return type with a structured suggestion instead of a note. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 55 ++++++++++++++++--- ...nd-lifetime-in-binding-only.elision.stderr | 6 +- ...und-lifetime-in-return-only.elision.stderr | 6 +- src/test/ui/foreign-fn-return-lifetime.fixed | 18 ++++++ src/test/ui/foreign-fn-return-lifetime.rs | 6 +- src/test/ui/foreign-fn-return-lifetime.stderr | 10 ++-- src/test/ui/issues/issue-13497.stderr | 6 +- src/test/ui/issues/issue-26638.stderr | 12 ++-- ...urn-type-requires-explicit-lifetime.stderr | 24 +++++--- .../lifetime-elision-return-type-trait.rs | 10 ++++ .../lifetime-elision-return-type-trait.stderr | 19 +++++++ .../underscore-lifetime-binders.stderr | 6 +- 13 files changed, 146 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/foreign-fn-return-lifetime.fixed create mode 100644 src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs create mode 100644 src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index cce872927b147..04a2308cead34 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1152,7 +1152,7 @@ impl<'a> LoweringContext<'a> { TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Rptr(ref region, ref mt) => { - let span = t.span.shrink_to_lo(); + let span = self.sess.source_map().next_point(t.span.shrink_to_lo()); let lifetime = match *region { Some(ref lt) => self.lower_lifetime(lt), None => self.elided_ref_lifetime(span), diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 98e80d333c1c8..86db74b78b983 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2238,7 +2238,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { if let Some(params) = error { if lifetime_refs.len() == 1 { - self.report_elision_failure(&mut err, params); + self.report_elision_failure(&mut err, params, span); } } @@ -2249,6 +2249,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { &mut self, db: &mut DiagnosticBuilder<'_>, params: &[ElisionFailureInfo], + span: Span, ) { let mut m = String::new(); let len = params.len(); @@ -2304,7 +2305,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { "this function's return type contains a borrowed value, but \ there is no value for it to be borrowed from" ); - help!(db, "consider giving it a 'static lifetime"); + let msg = "consider giving it a 'static lifetime"; + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability( + span, + msg, + "&'static ".to_owned(), + Applicability::MachineApplicable, + ), + Ok(ref snippet) + if snippet == "'_" => db.span_suggestion_with_applicability( + span, + msg, + "'static".to_owned(), + Applicability::MachineApplicable, + ), + Ok(ref snippet) => db.span_suggestion_with_applicability( + span, + msg, + format!("{} + 'static", snippet), + Applicability::MaybeIncorrect, + ), + Err(_) => db.help(msg), + }; } else if elided_len == 0 { help!( db, @@ -2312,11 +2335,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { an elided lifetime, but the lifetime cannot be derived from \ the arguments" ); - help!( - db, - "consider giving it an explicit bounded or 'static \ - lifetime" - ); + let msg = "consider giving it an explicit bounded or 'static lifetime"; + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability( + span, + msg, + "&'static ".to_owned(), + Applicability::MachineApplicable, + ), + Ok(ref snippet) + if snippet == "'_" => db.span_suggestion_with_applicability( + span, + msg, + "'static".to_owned(), + Applicability::MachineApplicable, + ), + Ok(ref snippet) => db.span_suggestion_with_applicability( + span, + msg, + format!("{} + 'static", snippet), + Applicability::MaybeIncorrect, + ), + Err(_) => db.help(msg), + }; } else if elided_len == 1 { help!( db, diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr index 0a12aa76a785b..4336aaf71ba02 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-binding-only.rs:62:23 | LL | fn elision &i32>() { - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to previous error diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr index 8fefdfd4d19ef..fbc4df54225d5 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-return-only.rs:44:23 | LL | fn elision(_: fn() -> &i32) { - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to previous error diff --git a/src/test/ui/foreign-fn-return-lifetime.fixed b/src/test/ui/foreign-fn-return-lifetime.fixed new file mode 100644 index 0000000000000..9fc35eae7052f --- /dev/null +++ b/src/test/ui/foreign-fn-return-lifetime.fixed @@ -0,0 +1,18 @@ +// Copyright 2017 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. + +// run-rustfix + +extern "C" { + pub fn g(_: &u8) -> &u8; // OK + pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/src/test/ui/foreign-fn-return-lifetime.rs b/src/test/ui/foreign-fn-return-lifetime.rs index da77066150cc7..941e7e05a3635 100644 --- a/src/test/ui/foreign-fn-return-lifetime.rs +++ b/src/test/ui/foreign-fn-return-lifetime.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + extern "C" { - fn g(_: &u8) -> &u8; // OK - fn f() -> &u8; //~ ERROR missing lifetime specifier + pub fn g(_: &u8) -> &u8; // OK + pub fn f() -> &u8; //~ ERROR missing lifetime specifier } fn main() {} diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr index ea15897b3d694..4e52d6044c4e9 100644 --- a/src/test/ui/foreign-fn-return-lifetime.stderr +++ b/src/test/ui/foreign-fn-return-lifetime.stderr @@ -1,11 +1,13 @@ error[E0106]: missing lifetime specifier - --> $DIR/foreign-fn-return-lifetime.rs:13:15 + --> $DIR/foreign-fn-return-lifetime.rs:15:19 | -LL | fn f() -> &u8; //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter +LL | pub fn f() -> &u8; //~ ERROR missing lifetime specifier + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to previous error diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr index ab6d041bd48d7..88b6a831d7e41 100644 --- a/src/test/ui/issues/issue-13497.stderr +++ b/src/test/ui/issues/issue-13497.stderr @@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-13497.rs:12:5 | LL | &str //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index cf6fcd9f01cc8..e4464b2dd313d 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -10,19 +10,23 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:14:40 | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments - = help: consider giving it an explicit bounded or 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:17:22 | LL | fn parse_type_3() -> &str { unimplemented!() } - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to 3 previous errors diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 30cff86ed1d40..9962dbc9812bd 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:12:11 | LL | fn f() -> &isize { //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:33 @@ -27,28 +29,34 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:31:20 | LL | fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments - = help: consider giving it an explicit bounded or 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:44:24 | LL | fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments - = help: consider giving it an explicit bounded or 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:50:49 | LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments - = help: consider giving it an explicit bounded or 'static lifetime error: aborting due to 6 previous errors diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs new file mode 100644 index 0000000000000..6b6e263b7fd1a --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -0,0 +1,10 @@ +trait Future { + type Item; + type Error; +} + +use std::error::Error; + +fn foo() -> impl Future> { + Ok(()) +} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr new file mode 100644 index 0000000000000..426941b949daa --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -0,0 +1,19 @@ +error[E0601]: `main` function not found in crate `lifetime_elision_return_type_trait` + | + = note: consider adding a `main` function to `$DIR/lifetime-elision-return-type-trait.rs` + +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-trait.rs:8:44 + | +LL | fn foo() -> impl Future> { + | ^^^^^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `Error + 'static` + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from + +error: aborting due to 2 previous errors + +Some errors occurred: E0106, E0601. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index fc9f3e642d402..b0da67a7c346e 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -26,10 +26,12 @@ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:24:29 | LL | fn meh() -> Box Meh<'_>> //~ ERROR cannot be used here - | ^^ expected lifetime parameter + | ^^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:30:35 From d0bd69a2d559177724df95463a79af9c2a2ad63d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 18 Oct 2018 13:05:38 -0700 Subject: [PATCH 39/54] review comments --- src/librustc/middle/resolve_lifetime.rs | 99 ++++++++----------- ...nd-lifetime-in-binding-only.elision.stderr | 5 +- ...und-lifetime-in-return-only.elision.stderr | 5 +- src/test/ui/foreign-fn-return-lifetime.stderr | 5 +- src/test/ui/issues/issue-13497.stderr | 5 +- src/test/ui/issues/issue-26638.stderr | 10 +- ...urn-type-requires-explicit-lifetime.stderr | 20 +--- .../lifetime-elision-return-type-trait.stderr | 5 +- .../underscore-lifetime-binders.stderr | 5 +- 9 files changed, 54 insertions(+), 105 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 86db74b78b983..7547e8039158e 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2235,22 +2235,46 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }; let mut err = report_missing_lifetime_specifiers(self.tcx.sess, span, lifetime_refs.len()); + let mut add_label = true; if let Some(params) = error { if lifetime_refs.len() == 1 { - self.report_elision_failure(&mut err, params, span); + add_label = add_label && self.report_elision_failure(&mut err, params, span); } } + if add_label { + add_missing_lifetime_specifiers_label(&mut err, span, lifetime_refs.len()); + } err.emit(); } + fn suggest_lifetime(&self, db: &mut DiagnosticBuilder<'_>, span: Span, msg: &str) -> bool { + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(ref snippet) => { + let (sugg, applicability) = if &snippet[..] == "&" { + ("&'static ".to_owned(), Applicability::MachineApplicable) + } else if snippet == "'_" { + ("'static".to_owned(), Applicability::MachineApplicable) + } else { + (format!("{} + 'static", snippet), Applicability::MaybeIncorrect) + }; + db.span_suggestion_with_applicability(span, msg, sugg, applicability); + false + } + Err(_) => { + db.help(msg); + true + } + } + } + fn report_elision_failure( &mut self, db: &mut DiagnosticBuilder<'_>, params: &[ElisionFailureInfo], span: Span, - ) { + ) -> bool { let mut m = String::new(); let len = params.len(); @@ -2305,29 +2329,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { "this function's return type contains a borrowed value, but \ there is no value for it to be borrowed from" ); - let msg = "consider giving it a 'static lifetime"; - match self.tcx.sess.source_map().span_to_snippet(span) { - Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability( - span, - msg, - "&'static ".to_owned(), - Applicability::MachineApplicable, - ), - Ok(ref snippet) - if snippet == "'_" => db.span_suggestion_with_applicability( - span, - msg, - "'static".to_owned(), - Applicability::MachineApplicable, - ), - Ok(ref snippet) => db.span_suggestion_with_applicability( - span, - msg, - format!("{} + 'static", snippet), - Applicability::MaybeIncorrect, - ), - Err(_) => db.help(msg), - }; + self.suggest_lifetime(db, span, "consider giving it a 'static lifetime") } else if elided_len == 0 { help!( db, @@ -2336,28 +2338,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { the arguments" ); let msg = "consider giving it an explicit bounded or 'static lifetime"; - match self.tcx.sess.source_map().span_to_snippet(span) { - Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability( - span, - msg, - "&'static ".to_owned(), - Applicability::MachineApplicable, - ), - Ok(ref snippet) - if snippet == "'_" => db.span_suggestion_with_applicability( - span, - msg, - "'static".to_owned(), - Applicability::MachineApplicable, - ), - Ok(ref snippet) => db.span_suggestion_with_applicability( - span, - msg, - format!("{} + 'static", snippet), - Applicability::MaybeIncorrect, - ), - Err(_) => db.help(msg), - }; + self.suggest_lifetime(db, span, msg) } else if elided_len == 1 { help!( db, @@ -2365,6 +2346,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { the signature does not say which {} it is borrowed from", m ); + true } else { help!( db, @@ -2372,6 +2354,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { the signature does not say whether it is borrowed from {}", m ); + true } } @@ -2785,26 +2768,28 @@ fn insert_late_bound_lifetimes( } } -pub fn report_missing_lifetime_specifiers( +fn report_missing_lifetime_specifiers( sess: &Session, span: Span, count: usize, ) -> DiagnosticBuilder<'_> { - let mut err = struct_span_err!( + struct_span_err!( sess, span, E0106, "missing lifetime specifier{}", if count > 1 { "s" } else { "" } - ); + ) +} - let msg: Cow<'static, str> = if count > 1 { - format!("expected {} lifetime parameters", count).into() +fn add_missing_lifetime_specifiers_label( + err: &mut DiagnosticBuilder<'_>, + span: Span, + count: usize, +) { + if count > 1 { + err.span_label(span, format!("expected {} lifetime parameters", count)); } else { - "expected lifetime parameter".into() + err.span_label(span, "expected lifetime parameter"); }; - - err.span_label(span, msg); - - err } diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr index 4336aaf71ba02..6b9d4ebb2987d 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-binding-only.rs:62:23 | LL | fn elision &i32>() { - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr index fbc4df54225d5..7906f0a30e4eb 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-return-only.rs:44:23 | LL | fn elision(_: fn() -> &i32) { - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr index 4e52d6044c4e9..583487656f24d 100644 --- a/src/test/ui/foreign-fn-return-lifetime.stderr +++ b/src/test/ui/foreign-fn-return-lifetime.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/foreign-fn-return-lifetime.rs:15:19 | LL | pub fn f() -> &u8; //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr index 88b6a831d7e41..e592452b89944 100644 --- a/src/test/ui/issues/issue-13497.stderr +++ b/src/test/ui/issues/issue-13497.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-13497.rs:12:5 | LL | &str //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index e4464b2dd313d..0ac6316f0dcf8 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -10,10 +10,7 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:14:40 | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } - | ^ - | | - | expected lifetime parameter - | help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments @@ -21,10 +18,7 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:17:22 | LL | fn parse_type_3() -> &str { unimplemented!() } - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 9962dbc9812bd..4c7a1b5ea9ff0 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:12:11 | LL | fn f() -> &isize { //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from @@ -29,10 +26,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:31:20 | LL | fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments @@ -40,10 +34,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:44:24 | LL | fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments @@ -51,10 +42,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:50:49 | LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { - | ^ - | | - | expected lifetime parameter - | help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index 426941b949daa..ab429b9df06cd 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -6,10 +6,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-trait.rs:8:44 | LL | fn foo() -> impl Future> { - | ^^^^^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `Error + 'static` + | ^^^^^ help: consider giving it a 'static lifetime: `Error + 'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index b0da67a7c346e..4319843291a20 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -26,10 +26,7 @@ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:24:29 | LL | fn meh() -> Box Meh<'_>> //~ ERROR cannot be used here - | ^^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `'static` + | ^^ help: consider giving it a 'static lifetime: `'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from From dd91c8fc5a7c097c508cdffdd236adc64dae01c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Fri, 19 Oct 2018 10:43:43 -0700 Subject: [PATCH 40/54] [review comments] modify test and clean up code Co-Authored-By: estebank --- src/librustc/middle/resolve_lifetime.rs | 2 +- .../ui/lifetimes/lifetime-elision-return-type-trait.rs | 2 ++ .../lifetimes/lifetime-elision-return-type-trait.stderr | 9 ++------- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 7547e8039158e..361abb1689619 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2252,7 +2252,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn suggest_lifetime(&self, db: &mut DiagnosticBuilder<'_>, span: Span, msg: &str) -> bool { match self.tcx.sess.source_map().span_to_snippet(span) { Ok(ref snippet) => { - let (sugg, applicability) = if &snippet[..] == "&" { + let (sugg, applicability) = if snippet == "&" { ("&'static ".to_owned(), Applicability::MachineApplicable) } else if snippet == "'_" { ("'static".to_owned(), Applicability::MachineApplicable) diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs index 6b6e263b7fd1a..eb959bfbcb533 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -8,3 +8,5 @@ use std::error::Error; fn foo() -> impl Future> { Ok(()) } + +fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index ab429b9df06cd..b2a3d9a94361f 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `lifetime_elision_return_type_trait` - | - = note: consider adding a `main` function to `$DIR/lifetime-elision-return-type-trait.rs` - error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-trait.rs:8:44 | @@ -10,7 +6,6 @@ LL | fn foo() -> impl Future> { | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0106, E0601. -For more information about an error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0106`. From 4f2624cac90ee9145175d6e4b9c59b9ab7875a9c Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 22 Oct 2018 00:12:16 -0400 Subject: [PATCH 41/54] Fix Rustdoc ICE when checking blanket impls Fixes #55001, #54744 Previously, SelectionContext would unconditionally cache the selection result for an obligation. This worked fine for most users of SelectionContext, but it caused an issue when used by Rustdoc's blanket impl finder. The issue occured when SelectionContext chose a ParamCandidate which contained inference variables. Since inference variables can change between calls to select(), it's not safe to cache the selection result - the chosen candidate might not be applicable for future results, leading to an ICE when we try to run confirmation. This commit prevents SelectionContext from caching any ParamCandidate that contains inference variables. This should always be completely safe, as trait selection should never depend on a particular result being cached. I've also added some extra debug!() statements, which I found helpful in tracking down this bug. --- src/librustc/infer/combine.rs | 10 +++++++- src/librustc/infer/equate.rs | 3 +++ src/librustc/traits/select.rs | 35 ++++++++++++++++++++++++++++ src/librustdoc/clean/blanket_impl.rs | 11 +++++++-- src/test/rustdoc/issue-55001.rs | 31 ++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/issue-55001.rs diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index de8f57ee79666..0ee03bc4c6e00 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -251,6 +251,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { dir: RelationDir) -> RelateResult<'tcx, Generalization<'tcx>> { + debug!("generalize(ty={:?}, for_vid={:?}, dir={:?}", ty, for_vid, dir); // Determine the ambient variance within which `ty` appears. // The surrounding equation is: // @@ -273,8 +274,15 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { root_ty: ty, }; - let ty = generalize.relate(&ty, &ty)?; + let ty = match generalize.relate(&ty, &ty) { + Ok(ty) => ty, + Err(e) => { + debug!("generalize: failure {:?}", e); + return Err(e); + } + }; let needs_wf = generalize.needs_wf; + debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf); Ok(Generalization { ty, needs_wf }) } } diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 854960492c9bd..c7b5ddb83410f 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -74,6 +74,9 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> let infcx = self.fields.infcx; let a = infcx.type_variables.borrow_mut().replace_if_possible(a); let b = infcx.type_variables.borrow_mut().replace_if_possible(b); + + debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b); + match (&a.sty, &b.sty) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().equate(a_id, b_id); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 39c623de677d3..3f4aa3a500d71 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1522,6 +1522,33 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map(|v| v.get(tcx)) } + /// Determines whether can we safely cache the result + /// of selecting an obligation. This is almost always 'true', + /// except when dealing with certain ParamCandidates. + /// + /// Ordinarily, a ParamCandidate will contain no inference variables, + /// since it was usually produced directly from a DefId. However, + /// certain cases (currently only librustdoc's blanket impl finder), + /// a ParamEnv may be explicitly constructed with inference types. + /// When this is the case, we do *not* want to cache the resulting selection + /// candidate. This is due to the fact that it might not always be possible + /// to equate the obligation's trait ref and the candidate's trait ref, + /// if more constraints end up getting added to an inference variable. + /// + /// Because of this, we always want to re-run the full selection + /// process for our obligation the next time we see it, since + /// we might end up picking a different SelectionCandidate (or none at all) + fn can_cache_candidate(&self, + result: &SelectionResult<'tcx, SelectionCandidate<'tcx>> + ) -> bool { + match result { + Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => { + !trait_ref.skip_binder().input_types().any(|t| t.walk().any(|t_| t_.is_ty_infer())) + }, + _ => true + } + } + fn insert_candidate_cache( &mut self, param_env: ty::ParamEnv<'tcx>, @@ -1531,6 +1558,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ) { let tcx = self.tcx(); let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; + + if !self.can_cache_candidate(&candidate) { + debug!("insert_candidate_cache(trait_ref={:?}, candidate={:?} -\ + candidate is not cacheable", trait_ref, candidate); + return; + + } + if self.can_use_global_caches(param_env) { if let Err(Overflow) = candidate { // Don't cache overflow globally; we only produce this diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index b6bc8d603d5ac..57c7e2afd625e 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -50,6 +50,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { name: Option, ) -> Vec where F: Fn(DefId) -> Def { + debug!("get_blanket_impls(def_id={:?}, ...)", def_id); let mut impls = Vec::new(); if self.cx .tcx @@ -78,6 +79,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { } self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { self.cx.tcx.infer_ctxt().enter(|infcx| { + debug!("get_blanet_impls: Considering impl for trait '{:?}' {:?}", + trait_def_id, impl_def_id); let t_generics = infcx.tcx.generics_of(impl_def_id); let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id) .expect("Cannot get impl trait"); @@ -104,8 +107,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { drop(obligations); debug!( - "invoking predicate_may_hold: {:?}", - trait_ref, + "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}", + param_env, trait_ref, ty ); let may_apply = match infcx.evaluate_obligation( &traits::Obligation::new( @@ -117,6 +120,10 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { Ok(eval_result) => eval_result.may_apply(), Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no }; + debug!("get_blanket_impls: found applicable impl: {}\ + for trait_ref={:?}, ty={:?}", + may_apply, trait_ref, ty); + if !may_apply { return } diff --git a/src/test/rustdoc/issue-55001.rs b/src/test/rustdoc/issue-55001.rs new file mode 100644 index 0000000000000..f6c7f9a3d082c --- /dev/null +++ b/src/test/rustdoc/issue-55001.rs @@ -0,0 +1,31 @@ +// Regression test for issue #55001. Previously, we would incorrectly +// cache certain trait selection results when checking for blanket impls, +// resulting in an ICE when we tried to confirm the cached ParamCandidate +// against an obligation. + +pub struct DefaultAllocator; +pub struct Standard; +pub struct Inner; + +pub trait Rand {} + +pub trait Distribution {} +pub trait Allocator {} + +impl Rand for T where Standard: Distribution {} + +impl Distribution> for Standard +where +DefaultAllocator: Allocator, +Standard: Distribution {} + +impl Distribution for Standard {} + + +pub struct Point +where DefaultAllocator: Allocator +{ + field: N +} + +fn main() {} From fda3326a5a34fd365e20f0dd2632cec27233d060 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 23 Oct 2018 17:13:59 +0900 Subject: [PATCH 42/54] Remove redundant clone --- src/librustc/hir/print.rs | 2 +- src/librustc/ich/caching_codemap_view.rs | 2 +- src/librustc/traits/project.rs | 2 +- src/librustc/ty/sty.rs | 2 +- src/librustc_mir/hair/pattern/_match.rs | 4 ++-- src/libsyntax/fold.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 08d46793d97bf..ad2fa48610b0e 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -180,7 +180,7 @@ impl<'a> State<'a> { State { s: pp::mk_printer(out, default_columns), cm: Some(cm), - comments: comments.clone(), + comments, literals: literals.unwrap_or_default().into_iter().peekable(), cur_cmnt: 0, boxes: Vec::new(), diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs index 97114779042af..fbf4297222f9b 100644 --- a/src/librustc/ich/caching_codemap_view.rs +++ b/src/librustc/ich/caching_codemap_view.rs @@ -44,7 +44,7 @@ impl<'cm> CachingSourceMapView<'cm> { CachingSourceMapView { source_map, - line_cache: [entry.clone(), entry.clone(), entry.clone()], + line_cache: [entry.clone(), entry.clone(), entry], time_stamp: 0, } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b29ee8f7cdce4..b266fbe0d1145 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -340,7 +340,7 @@ impl<'a, 'b, 'gcx, 'tcx> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> { let value = self.selcx.infcx().resolve_type_vars_if_possible(value); if !value.has_projections() { - value.clone() + value } else { value.fold_with(self) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 8289158387015..0acf711c238d2 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -967,7 +967,7 @@ impl<'tcx> PolyFnSig<'tcx> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } pub fn output(&self) -> ty::Binder> { - self.map_bound_ref(|fn_sig| fn_sig.output().clone()) + self.map_bound_ref(|fn_sig| fn_sig.output()) } pub fn variadic(&self) -> bool { self.skip_binder().variadic diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 04a297d0a8317..77483ad184ba6 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1048,7 +1048,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, if let Some(constructors) = pat_constructors(cx, v[0], pcx) { debug!("is_useful - expanding constructors: {:#?}", constructors); split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c| - is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) + is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) ).find(|result| result.is_useful()).unwrap_or(NotUseful) } else { debug!("is_useful - expanding wildcard"); @@ -1096,7 +1096,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, if missing_ctors.is_empty() && !is_non_exhaustive { split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| { - is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) + is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) }).find(|result| result.is_useful()).unwrap_or(NotUseful) } else { let matrix = rows.iter().filter_map(|r| { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 95a2298ca757d..18d5970462f63 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -965,7 +965,7 @@ pub fn noop_fold_item_kind(i: ItemKind, folder: &mut T) -> ItemKind { polarity, defaultness, folder.fold_generics(generics), - ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref.clone())), + ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref)), folder.fold_ty(ty), impl_items.move_flat_map(|item| folder.fold_impl_item(item)), ), From 2d960a561061d78d44c3c56d3aa0fa6975ca0ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Tue, 23 Oct 2018 13:39:30 +0200 Subject: [PATCH 43/54] Update dangling-alloc-id-ice-2.rs --- src/test/ui/consts/dangling-alloc-id-ice-2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.rs b/src/test/ui/consts/dangling-alloc-id-ice-2.rs index 9af72c8dc0b83..b4691641fc98f 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice-2.rs +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.rs @@ -1,4 +1,4 @@ -// https://github.com/rust-lang/rust/issues/55223 +// FIXME(#55223) this is just a reproduction test showing the wrong behavior struct Slice(&'static [&'static [u8]]); From 8d6ee8f54ad802231f1e09e4b4433ef84d8a4248 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Tue, 23 Oct 2018 07:53:48 -0400 Subject: [PATCH 44/54] Do some copy editing on the release notes I was reading through the release notes to find something and noticed some small grammatical and consistency issues. --- RELEASES.md | 88 ++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 7ae7dc9935b6d..1d888731e94a2 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4,34 +4,34 @@ Version 1.30.0 (2018-10-25) Language -------- - [Procedural macros are now available.][52081] These kinds of macros allow for - more powerful code generation, there is a [new chapter available][proc-macros] - in Rust Programming Language book that goes further in depth. + more powerful code generation. There is a [new chapter available][proc-macros] + in the Rust Programming Language book that goes further in depth. - [You can now use keywords as identifiers using the raw identifiers - syntax (`r#`).][53236] e.g. `let r#for = true;` + syntax (`r#`),][53236] e.g. `let r#for = true;` - [Using anonymous parameters in traits is now deprecated with a warning and will be a hard error in the 2018 edition.][53272] - [You can now use `crate` in paths.][54404] This allows you to refer to the - crate root in the path. e.g. `use crate::foo;` refers to `foo` in `src/lib.rs`. -- [Using a external crate now no longer requires being prefixed with `::`.][54404] - e.g. previously using a external crate in a module without a use statement - required `let json = ::serde_json::from_str(foo);` can now be written + crate root in the path, e.g. `use crate::foo;` refers to `foo` in `src/lib.rs`. +- [Using a external crate no longer requires being prefixed with `::`.][54404] + Previously, using a external crate in a module without a use statement + required `let json = ::serde_json::from_str(foo);` but can now be written as `let json = serde_json::from_str(foo);`. - [You can now apply the `#[used]` attribute to static items to prevent the - compiler from optimising them away even if they appear to be unused.][51363] + compiler from optimising them away, even if they appear to be unused,][51363] e.g. `#[used] static FOO: u32 = 1;` - [You can now import and reexport macros from other crates with the `use` syntax.][50911] Macros exported with `#[macro_export]` are now placed into the root module of the crate. If your macro relies on calling other local - macros it is recommended to export with the - `#[macro_export(local_inner_macros)]` attribute so that users won't have to - import those macros. -- [`mod.rs` files are now optional.][54146] Previously if you had a `foo` module + macros, it is recommended to export with the + `#[macro_export(local_inner_macros)]` attribute so users won't have to import + those macros. +- [`mod.rs` files are now optional.][54146] Previously, if you had a `foo` module with a `bar` submodule, you would have `src/foo/mod.rs` and `src/foo/bar.rs`. Now you can have `src/foo.rs` and `src/foo/bar.rs` to achieve the same effect. - [You can now catch visibility keywords (e.g. `pub`, `pub(crate)`) in macros using the `vis` specifier.][53370] -- [Non-macro attributes now allow all forms of literals not just - strings.][53044] e.g. Previously you would write `#[attr("true")]` you can now +- [Non-macro attributes now allow all forms of literals, not just + strings.][53044] Previously, you would write `#[attr("true")]`, and you can now write `#[attr(true)]`. - [You can now specify a function to handle a panic in the Rust runtime with the `#[panic_handler]` attribute.][51366] @@ -54,9 +54,9 @@ Stabilized APIs - [`Ipv6Addr::UNSPECIFIED`] - [`Iterator::find_map`] - The following methods are a replacement methods for `trim_left`, `trim_right`, - `trim_left_matches`, and `trim_right_matches`. Which will be deprecated - in 1.33.0. + The following methods are replacement methods for `trim_left`, `trim_right`, + `trim_left_matches`, and `trim_right_matches`, which will be deprecated + in 1.33.0: - [`str::trim_end_matches`] - [`str::trim_end`] - [`str::trim_start_matches`] @@ -76,12 +76,12 @@ Misc ---- - [`rustdoc` allows you to specify what edition to treat your code as with the `--edition` option.][54057] -- [`rustdoc` now has the `--color` (Specify whether to output color) and - `--error-format` (Specify error format e.g. `json`) options.][53003] +- [`rustdoc` now has the `--color` (specify whether to output color) and + `--error-format` (specify error format, e.g. `json`) options.][53003] - [We now distribute a `rust-gdbgui` script that invokes `gdbgui` with Rust debug symbols.][53774] - [Attributes from Rust tools such as `rustfmt` or `clippy` are now - available.][53459] e.g. `#[rustfmt::skip]` will skip formatting the next item. + available,][53459] e.g. `#[rustfmt::skip]` will skip formatting the next item. [50911]: https://github.com/rust-lang/rust/pull/50911/ [51363]: https://github.com/rust-lang/rust/pull/51363/ @@ -153,7 +153,7 @@ Compiler Libraries --------- -- [`Once::call_once` now no longer requires `Once` to be `'static`.][52239] +- [`Once::call_once` no longer requires `Once` to be `'static`.][52239] - [`BuildHasherDefault` now implements `PartialEq` and `Eq`.][52402] - [`Box`, `Box`, and `Box` now implement `Clone`.][51912] - [Implemented `PartialEq<&str>` for `OsString` and `PartialEq` @@ -169,10 +169,10 @@ Stabilized APIs Cargo ----- -- [Cargo can silently fix some bad lockfiles ][cargo/5831] You can use - `--locked` to disable this behaviour. +- [Cargo can silently fix some bad lockfiles.][cargo/5831] You can use + `--locked` to disable this behavior. - [`cargo-install` will now allow you to cross compile an install - using `--target`][cargo/5614] + using `--target`.][cargo/5614] - [Added the `cargo-fix` subcommand to automatically move project code from 2015 edition to 2018.][cargo/5723] - [`cargo doc` can now optionally document private types using the @@ -184,15 +184,15 @@ Misc the specified level to that level.][52354] For example `--cap-lints warn` will demote `deny` and `forbid` lints to `warn`. - [`rustc` and `rustdoc` will now have the exit code of `1` if compilation - fails, and `101` if there is a panic.][52197] + fails and `101` if there is a panic.][52197] - [A preview of clippy has been made available through rustup.][51122] - You can install the preview with `rustup component add clippy-preview` + You can install the preview with `rustup component add clippy-preview`. Compatibility Notes ------------------- - [`str::{slice_unchecked, slice_unchecked_mut}` are now deprecated.][51807] Use `str::get_unchecked(begin..end)` instead. -- [`std::env::home_dir` is now deprecated for its unintuitive behaviour.][51656] +- [`std::env::home_dir` is now deprecated for its unintuitive behavior.][51656] Consider using the `home_dir` function from https://crates.io/crates/dirs instead. - [`rustc` will no longer silently ignore invalid data in target spec.][52330] @@ -432,7 +432,7 @@ Language be used as an identifier. - [The dyn syntax is now available.][49968] This syntax is equivalent to the bare `Trait` syntax, and should make it clearer when being used in tandem with - `impl Trait`. Since it is equivalent to the following syntax: + `impl Trait` because it is equivalent to the following syntax: `&Trait == &dyn Trait`, `&mut Trait == &mut dyn Trait`, and `Box == Box`. - [Attributes on generic parameters such as types and lifetimes are @@ -495,10 +495,10 @@ Cargo a different directory than `target` for placing compilation artifacts. - [Cargo will be adding automatic target inference for binaries, benchmarks, examples, and tests in the Rust 2018 edition.][cargo/5335] If your project specifies - specific targets e.g. using `[[bin]]` and have other binaries in locations + specific targets, e.g. using `[[bin]]`, and have other binaries in locations where cargo would infer a binary, Cargo will produce a warning. You can - disable this feature ahead of time by setting any of the following `autobins`, - `autobenches`, `autoexamples`, `autotests` to false. + disable this feature ahead of time by setting any of the following to false: + `autobins`, `autobenches`, `autoexamples`, `autotests`. - [Cargo will now cache compiler information.][cargo/5359] This can be disabled by setting `CARGO_CACHE_RUSTC_INFO=0` in your environment. @@ -514,8 +514,8 @@ Compatibility Notes work.][49896] e.g. `::core::prelude::v1::StrExt::is_empty("")` will not compile, `"".is_empty()` will still compile. - [`Debug` output on `atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize}` - will only print the inner type.][48553] e.g. - `print!("{:?}", AtomicBool::new(true))` will print `true` + will only print the inner type.][48553] E.g. + `print!("{:?}", AtomicBool::new(true))` will print `true`, not `AtomicBool(true)`. - [The maximum number for `repr(align(N))` is now 2²⁹.][50378] Previously you could enter higher numbers but they were not supported by LLVM. Up to 512MB @@ -578,7 +578,7 @@ Version 1.26.2 (2018-06-05) Compatibility Notes ------------------- -- [The borrow checker was fixed to avoid unsoundness when using match ergonomics][51117] +- [The borrow checker was fixed to avoid unsoundness when using match ergonomics.][51117] [51117]: https://github.com/rust-lang/rust/issues/51117 @@ -589,18 +589,18 @@ Version 1.26.1 (2018-05-29) Tools ----- -- [RLS now works on Windows][50646] -- [Rustfmt stopped badly formatting text in some cases][rustfmt/2695] +- [RLS now works on Windows.][50646] +- [Rustfmt stopped badly formatting text in some cases.][rustfmt/2695] Compatibility Notes -------- - [`fn main() -> impl Trait` no longer works for non-Termination - trait][50656] + trait.][50656] This reverts an accidental stabilization. -- [`NaN > NaN` no longer returns true in const-fn contexts][50812] -- [Prohibit using turbofish for `impl Trait` in method arguments][50950] +- [`NaN > NaN` no longer returns true in const-fn contexts.][50812] +- [Prohibit using turbofish for `impl Trait` in method arguments.][50950] [50646]: https://github.com/rust-lang/rust/issues/50646 [50656]: https://github.com/rust-lang/rust/pull/50656 @@ -616,18 +616,18 @@ Language - [Closures now implement `Copy` and/or `Clone` if all captured variables implement either or both traits.][49299] - [The inclusive range syntax e.g. `for x in 0..=10` is now stable.][47813] -- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere where a +- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere a lifetime can be elided.][49458] - [`impl Trait` is now stable allowing you to have abstract types in returns - or in function parameters.][49255] e.g. `fn foo() -> impl Iterator` or + or in function parameters.][49255] E.g. `fn foo() -> impl Iterator` or `fn open(path: impl AsRef)`. - [Pattern matching will now automatically apply dereferences.][49394] - [128-bit integers in the form of `u128` and `i128` are now stable.][49101] - [`main` can now return `Result<(), E: Debug>`][49162] in addition to `()`. - [A lot of operations are now available in a const context.][46882] E.g. You can now index into constant arrays, reference and dereference into constants, - and use Tuple struct constructors. -- [Fixed entry slice patterns are now stable.][48516] e.g. + and use tuple struct constructors. +- [Fixed entry slice patterns are now stable.][48516] E.g. ```rust let points = [1, 2, 3, 4]; match points { @@ -1052,7 +1052,7 @@ Language Compiler -------- - [Enabled `TrapUnreachable` in LLVM which should mitigate the impact of - undefined behaviour.][45920] + undefined behavior.][45920] - [rustc now suggests renaming import if names clash.][45660] - [Display errors/warnings correctly when there are zero-width or wide characters.][45711] From 4972beaf65cad992a6ed791fdefe90e46c09aa7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 22 Oct 2018 18:21:55 +0200 Subject: [PATCH 45/54] fix typos in various places --- src/bootstrap/bootstrap.py | 2 +- src/etc/lldb_rust_formatters.py | 2 +- src/liballoc/collections/btree/map.rs | 2 +- src/libcore/alloc.rs | 2 +- src/libcore/intrinsics.rs | 2 +- src/libcore/pin.rs | 2 +- src/libcore/ptr.rs | 2 +- src/librustc/hir/def_id.rs | 4 ++-- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc_codegen_llvm/builder.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/diagnostics.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/interpret/memory.rs | 6 +++--- src/librustc_mir/interpret/operand.rs | 4 ++-- src/librustc_mir/interpret/validity.rs | 4 ++-- src/librustc_passes/ast_validation.rs | 16 ++++++++-------- src/librustc_target/abi/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/once.rs | 4 ++-- src/libsyntax/config.rs | 4 ++-- src/test/run-pass/issues/issue-18804/main.rs | 2 +- .../ui/block-result/unexpected-return-on-unit.rs | 2 +- .../cfg-attr-multi-false.rs | 2 +- .../ui/nll/issue-21232-partial-init-and-use.rs | 2 +- ...52059-report-when-borrow-and-drop-conflict.rs | 2 +- src/test/ui/resolve/token-error-correct-2.rs | 2 +- src/test/ui/resolve/token-error-correct-3.rs | 2 +- src/test/ui/resolve/token-error-correct.rs | 2 +- .../syntax-ambiguity-2015.rs | 12 ++++++------ .../syntax-ambiguity-2015.stderr | 12 ++++++------ .../syntax-ambiguity-2018.rs | 12 ++++++------ .../syntax-ambiguity-2018.stderr | 12 ++++++------ .../rust-2018/edition-lint-infer-outlives.fixed | 2 +- .../ui/rust-2018/edition-lint-infer-outlives.rs | 2 +- src/test/ui/specialization/issue-52050.rs | 2 +- src/tools/tidy/src/pal.rs | 2 +- 43 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c27f4f056d747..ffc5adbebb34f 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -594,7 +594,7 @@ def exe_suffix(): return '' def bootstrap_binary(self): - """Return the path of the boostrap binary + """Return the path of the bootstrap binary >>> rb = RustBuild() >>> rb.build_dir = "build" diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py index 4427313f9e5b3..2bbd4372721cb 100644 --- a/src/etc/lldb_rust_formatters.py +++ b/src/etc/lldb_rust_formatters.py @@ -277,7 +277,7 @@ def print_std_string_val(val, internal_dict): #=-------------------------------------------------------------------------------------------------- def print_array_of_values(array_name, data_ptr_val, length, internal_dict): - """Prints a contigous memory range, interpreting it as values of the + """Prints a contiguous memory range, interpreting it as values of the pointee-type of data_ptr_val.""" data_ptr_type = data_ptr_val.type diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 8c950cd06d9e3..24c8fd3a969ca 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -77,7 +77,7 @@ use self::Entry::*; /// movie_reviews.insert("Office Space", "Deals with real issues in the workplace."); /// movie_reviews.insert("Pulp Fiction", "Masterpiece."); /// movie_reviews.insert("The Godfather", "Very enjoyable."); -/// movie_reviews.insert("The Blues Brothers", "Eye lyked it alot."); +/// movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot."); /// /// // check for a specific one. /// if !movie_reviews.contains_key("Les Misérables") { diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 35e4eea756d41..4efcaae59b012 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -518,7 +518,7 @@ pub unsafe trait GlobalAlloc { /// The block is described by the given `ptr` pointer and `layout`. /// /// If this returns a non-null pointer, then ownership of the memory block - /// referenced by `ptr` has been transferred to this alloctor. + /// referenced by `ptr` has been transferred to this allocator. /// The memory may or may not have been deallocated, /// and should be considered unusable (unless of course it was /// transferred back to the caller again via the return value of diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 56a24168e28d9..cceae9249e456 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1025,7 +1025,7 @@ extern "rust-intrinsic" { /// // to avoid problems in case something further down panics. /// src.set_len(0); /// - /// // The two regions cannot overlap becuase mutable references do + /// // The two regions cannot overlap because mutable references do /// // not alias, and two different vectors cannot own the same /// // memory. /// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len); diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 0224560af4c76..a03c080fb3f34 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -102,7 +102,7 @@ pub use marker::Unpin; /// value in place, preventing the value referenced by that pointer from being moved /// unless it implements [`Unpin`]. /// -/// See the [`pin` module] documentation for furthur explanation on pinning. +/// See the [`pin` module] documentation for further explanation on pinning. /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 1c761ba21b3ec..b699cb028842b 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -38,7 +38,7 @@ //! underlying object is live and no reference (just raw pointers) is used to //! access the same memory. //! -//! These axioms, along with careful use of [`offset`] for pointer arithmentic, +//! These axioms, along with careful use of [`offset`] for pointer arithmetic, //! are enough to correctly implement many useful things in unsafe code. Stronger guarantees //! will be provided eventually, as the [aliasing] rules are being determined. For more //! information, see the [book] as well as the section in the reference devoted diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index a09fd5df557f5..e378e1b8be0e9 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -40,7 +40,7 @@ impl ::std::fmt::Debug for CrateNum { match self { CrateNum::Index(id) => write!(fmt, "crate{}", id.private), CrateNum::Invalid => write!(fmt, "invalid crate"), - CrateNum::BuiltinMacros => write!(fmt, "bultin macros crate"), + CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"), CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"), } } @@ -101,7 +101,7 @@ impl fmt::Display for CrateNum { match self { CrateNum::Index(id) => fmt::Display::fmt(&id.private, f), CrateNum::Invalid => write!(f, "invalid crate"), - CrateNum::BuiltinMacros => write!(f, "bultin macros crate"), + CrateNum::BuiltinMacros => write!(f, "builtin macros crate"), CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"), } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 4c2b2b2d41d1b..5054f52277870 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -632,7 +632,7 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result } //////////////////////////////////////////////////////////////////////////////// -// Methods to faciliate working with signed integers stored in a u128 +// Methods to facilitate working with signed integers stored in a u128 //////////////////////////////////////////////////////////////////////////////// pub fn sign_extend(value: u128, size: Size) -> u128 { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 62b5327ae4692..f1c5030c6419a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -469,7 +469,7 @@ pub enum BorrowKind { /// } /// /// This can't be a shared borrow because mutably borrowing (*x as Some).0 - /// should not prevent `if let None = x { ... }`, for example, becase the + /// should not prevent `if let None = x { ... }`, for example, because the /// mutating `(*x as Some).0` can't affect the discriminant of `x`. /// We can also report errors with this kind of borrow differently. Shallow, diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index dc0039926448c..ea30752a820ee 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -412,7 +412,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { flags.push(("crate_local".to_owned(), None)); } - // Allow targetting all integers using `{integral}`, even if the exact type was resolved + // Allow targeting all integers using `{integral}`, even if the exact type was resolved if self_ty.is_integral() { flags.push(("_Self".to_owned(), Some("{integral}".to_owned()))); } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 169bd9a8466a0..2fe6a0377f81b 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -761,7 +761,7 @@ impl Builder<'a, 'll, 'tcx> { fty, asm, cons, volatile, alignstack, dia); Some(self.call(v, inputs, None)) } else { - // LLVM has detected an issue with our constaints, bail out + // LLVM has detected an issue with our constraints, bail out None } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7988de28b5d7b..e6e1367b592df 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -68,7 +68,7 @@ macro_rules! provide { let $cdata = $tcx.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() - .expect("CrateStore crated ata is not a CrateMetadata"); + .expect("CrateStore created data is not a CrateMetadata"); $compute })* diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index bc917140bbd67..9702e94a9e0f0 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -129,7 +129,7 @@ pub fn op_to_const<'tcx>( assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes()); let mut alloc = alloc.clone(); alloc.align = align; - // FIXME shouldnt it be the case that `mark_static_initialized` has already + // FIXME shouldn't it be the case that `mark_static_initialized` has already // interned this? I thought that is the entire point of that `FinishStatic` stuff? let alloc = ecx.tcx.intern_const_alloc(alloc); ConstValue::ByRef(ptr.alloc_id, alloc, ptr.offset) diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index bb3e4a8d8813f..56a9daf84f768 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -2279,7 +2279,7 @@ fn demo<'a>(s: &'a mut S<'a>) -> &'a mut String { let p = &mut *(*s).data; p } Note that this approach needs a reference to S with lifetime `'a`. Nothing shorter than `'a` will suffice: a shorter lifetime would imply -that after `demo` finishes excuting, something else (such as the +that after `demo` finishes executing, something else (such as the destructor!) could access `s.data` after the end of that shorter lifetime, which would again violate the `&mut`-borrow's exclusive access. diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 189388921650c..64ad4c2eec1e1 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -556,7 +556,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc )?; } } else { - // Uh, that shouln't happen... the function did not intend to return + // Uh, that shouldn't happen... the function did not intend to return return err!(Unreachable); } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 9adca6c429798..6fe490c6efc8f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -94,7 +94,7 @@ impl<'a, 'b, 'c, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout } } -// FIXME: Really we shouldnt clone memory, ever. Snapshot machinery should instad +// FIXME: Really we shouldn't clone memory, ever. Snapshot machinery should instead // carefully copy only the reachable parts. impl<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> Clone for Memory<'a, 'mir, 'tcx, M> @@ -658,7 +658,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } /// It is the caller's responsibility to handle undefined and pointer bytes. - /// However, this still checks that there are no relocations on the *egdes*. + /// However, this still checks that there are no relocations on the *edges*. #[inline] fn get_bytes_with_undef_and_ptr( &self, @@ -1098,7 +1098,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } - /// Error if there are relocations overlapping with the egdes of the + /// Error if there are relocations overlapping with the edges of the /// given memory range. #[inline] fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 71b2f4b53a60c..021e2d58f84b1 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -357,14 +357,14 @@ fn from_known_layout<'tcx>( } impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { - /// Try reading a value in memory; this is interesting particularily for ScalarPair. + /// Try reading a value in memory; this is interesting particularly for ScalarPair. /// Return None if the layout does not permit loading this as a value. pub(super) fn try_read_value_from_mplace( &self, mplace: MPlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx, Option>> { if mplace.layout.is_unsized() { - // Dont touch unsized + // Don't touch unsized return Ok(None); } let (ptr, ptr_align) = mplace.to_scalar_ptr_align(); diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 38cf79d8fa0b9..ac1ba0edc3b3b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -230,7 +230,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ), } } - // non-ZST also have to be dereferencable + // non-ZST also have to be dereferenceable if size != Size::ZERO { let ptr = try_validation!(place.ptr.to_ptr(), "integer pointer in non-ZST reference", path); @@ -272,7 +272,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // FIXME: Check if the signature matches } // This should be all the primitive types - ty::Never => bug!("Uninhabited type should have been catched earlier"), + ty::Never => bug!("Uninhabited type should have been caught earlier"), _ => bug!("Unexpected primitive type {}", value.layout.ty) } Ok(()) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index f6ace57f5e0fb..0e9596244cd58 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -166,12 +166,12 @@ impl<'a> AstValidator<'a> { } } - /// With eRFC 2497, we need to check whether an expression is ambigious and warn or error + /// With eRFC 2497, we need to check whether an expression is ambiguous and warn or error /// depending on the edition, this function handles that. fn while_if_let_ambiguity(&self, expr: &P) { if let Some((span, op_kind)) = self.while_if_let_expr_ambiguity(&expr) { let mut err = self.err_handler().struct_span_err( - span, &format!("ambigious use of `{}`", op_kind.to_string()) + span, &format!("ambiguous use of `{}`", op_kind.to_string()) ); err.note( @@ -193,9 +193,9 @@ impl<'a> AstValidator<'a> { } /// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of - /// `&&` and `||` in a if-let statement be unambigious. This function returns a span and - /// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined - /// that the current expression parsed is ambigious and will break in future. + /// `&&` and `||` in a if-let statement be unambiguous. This function returns a span and + /// a `BinOpKind` (either `&&` or `||` depending on what was ambiguous) if it is determined + /// that the current expression parsed is ambiguous and will break in future. fn while_if_let_expr_ambiguity(&self, expr: &P) -> Option<(Span, BinOpKind)> { debug!("while_if_let_expr_ambiguity: expr.node: {:?}", expr.node); match &expr.node { @@ -203,12 +203,12 @@ impl<'a> AstValidator<'a> { Some((expr.span, op.node)) }, ExprKind::Range(ref lhs, ref rhs, _) => { - let lhs_ambigious = lhs.as_ref() + let lhs_ambiguous = lhs.as_ref() .and_then(|lhs| self.while_if_let_expr_ambiguity(lhs)); - let rhs_ambigious = rhs.as_ref() + let rhs_ambiguous = rhs.as_ref() .and_then(|rhs| self.while_if_let_expr_ambiguity(rhs)); - lhs_ambigious.or(rhs_ambigious) + lhs_ambiguous.or(rhs_ambiguous) } _ => None, } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 6b28fd091748f..1a5d2801af0c5 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -430,7 +430,7 @@ impl Align { } /// Lower the alignment, if necessary, such that the given offset - /// is aligned to it (the offset is a multiple of the aligment). + /// is aligned to it (the offset is a multiple of the alignment). pub fn restrict_for_offset(self, offset: Size) -> Align { self.min(Align::max_for_offset(offset)) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1c562859bb48d..77151351d08a1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5198,7 +5198,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { // If no type arguments were provided, we have to infer them. // This case also occurs as a result of some malformed input, e.g. - // a lifetime argument being given instead of a type paramter. + // a lifetime argument being given instead of a type parameter. // Using inference instead of `Error` gives better error messages. self.var_for_def(span, param) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ec773e384af38..9990d2ee2b676 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -674,7 +674,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( } // if may_define_existential_type // now register the bounds on the parameters of the existential type - // so the parameters given by the function need to fulfil them + // so the parameters given by the function need to fulfill them // ```rust // existential type Foo: 'static; // fn foo() -> Foo { .. *} diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c54d9e4b47578..05a83dd307c38 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -269,7 +269,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, // exactly one (non-phantom) field has changed its // type, which we will expect to be the pointer that // is becoming fat (we could probably generalize this - // to mutiple thin pointers of the same type becoming + // to multiple thin pointers of the same type becoming // fat, but we don't). In this case: // // - `extra` has type `T` before and type `T` after diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index d69ebc1762272..a7db372a0e20a 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -97,7 +97,7 @@ //! - A **multiprocessor** system executing multiple hardware threads //! at the same time: In multi-threaded scenarios, you can use two //! kinds of primitives to deal with synchronization: -//! - [memory fences] to ensure memory accesses are made visibile to +//! - [memory fences] to ensure memory accesses are made visible to //! other CPUs in the right order. //! - [atomic operations] to ensure simultaneous access to the same //! memory location doesn't lead to undefined behavior. diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 98845e457b25c..cf9698cb2a971 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -290,8 +290,8 @@ impl Once { } /// Returns true if some `call_once` call has completed - /// successfuly. Specifically, `is_completed` will return false in - /// the following situtations: + /// successfully. Specifically, `is_completed` will return false in + /// the following situations: /// * `call_once` was not called at all, /// * `call_once` was called, but has not yet completed, /// * the `Once` instance is poisoned diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index e611eb86dc1b3..d8fb20d425008 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -96,7 +96,7 @@ impl<'a> StripUnconfigured<'a> { /// when the configuration predicate is true, or otherwise expand into an /// empty list of attributes. /// - /// Gives a compiler warning when the `cfg_attr` contains no attribtes and + /// Gives a compiler warning when the `cfg_attr` contains no attributes and /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec { @@ -138,7 +138,7 @@ impl<'a> StripUnconfigured<'a> { }; // Check feature gate and lint on zero attributes in source. Even if the feature is gated, - // we still compute as if it wasn't, since the emitted error will stop compilation futher + // we still compute as if it wasn't, since the emitted error will stop compilation further // along the compilation. match (expanded_attrs.len(), gate_cfg_attr_multi) { (0, false) => { diff --git a/src/test/run-pass/issues/issue-18804/main.rs b/src/test/run-pass/issues/issue-18804/main.rs index a3a5337077cc6..2abcd4b7ba99c 100644 --- a/src/test/run-pass/issues/issue-18804/main.rs +++ b/src/test/run-pass/issues/issue-18804/main.rs @@ -9,7 +9,7 @@ // except according to those terms. // run-pass -// Test for issue #18804, #[linkage] does not propagate thorugh generic +// Test for issue #18804, #[linkage] does not propagate through generic // functions. Failure results in a linker error. // ignore-asmjs no weak symbol support diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs index 3cf76365c77b1..b116888d63c10 100644 --- a/src/test/ui/block-result/unexpected-return-on-unit.rs +++ b/src/test/ui/block-result/unexpected-return-on-unit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we do some basic error correcton in the tokeniser (and don't spew +// Test that we do some basic error correction in the tokeniser (and don't spew // too many bogus errors). fn foo() -> usize { diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs index 84bd33fc0e7d3..ec4ee80b498a5 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs @@ -1,5 +1,5 @@ // Test that cfg_attr doesn't emit any attributes when the -// configuation variable is false. This mirrors `cfg-attr-multi-true.rs` +// configuration variable is false. This mirrors `cfg-attr-multi-true.rs` // compile-pass diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs index e3ae4c0dcbe57..186ecc5482720 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs @@ -66,7 +66,7 @@ impl R { fn new(f: F) -> Self { R { w: 0, f } } } // It got pretty monotonous writing the same code over and over, and I // feared I would forget details. So I abstracted some desiderata into // macros. But I left the initialization code inline, because that's -// where the errors for #54986 will be emited. +// where the errors for #54986 will be emitted. macro_rules! use_fully { (struct $s:expr) => { { diff --git a/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs index fff73c6d0fa9c..eaa809d2b3706 100644 --- a/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs +++ b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs @@ -1,5 +1,5 @@ // rust-lang/rust#52059: Regardless of whether you are moving out of a -// Drop type or just introducing an inadvertant alias via a borrow of +// Drop type or just introducing an inadvertent alias via a borrow of // one of its fields, it is useful to be reminded of the significance // of the fact that the type implements Drop. diff --git a/src/test/ui/resolve/token-error-correct-2.rs b/src/test/ui/resolve/token-error-correct-2.rs index e49374f9ce649..55803e4034bf4 100644 --- a/src/test/ui/resolve/token-error-correct-2.rs +++ b/src/test/ui/resolve/token-error-correct-2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we do some basic error correcton in the tokeniser (and don't ICE). +// Test that we do some basic error correction in the tokeniser (and don't ICE). fn main() { if foo { diff --git a/src/test/ui/resolve/token-error-correct-3.rs b/src/test/ui/resolve/token-error-correct-3.rs index 8881b965f9480..fd4bbde28660e 100644 --- a/src/test/ui/resolve/token-error-correct-3.rs +++ b/src/test/ui/resolve/token-error-correct-3.rs @@ -10,7 +10,7 @@ // ignore-cloudabi no std::fs support -// Test that we do some basic error correcton in the tokeniser (and don't spew +// Test that we do some basic error correction in the tokeniser (and don't spew // too many bogus errors). pub mod raw { diff --git a/src/test/ui/resolve/token-error-correct.rs b/src/test/ui/resolve/token-error-correct.rs index 39c664e270c45..099ead93beb06 100644 --- a/src/test/ui/resolve/token-error-correct.rs +++ b/src/test/ui/resolve/token-error-correct.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we do some basic error correcton in the tokeniser. +// Test that we do some basic error correction in the tokeniser. fn main() { foo(bar(; diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs index 339d49104b021..31a34a9e6fbbb 100644 --- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs +++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs @@ -19,22 +19,22 @@ fn main() { use std::ops::Range; if let Range { start: _, end: _ } = true..true && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` if let Range { start: _, end: _ } = true..true || false { } - //~^ ERROR ambigious use of `||` + //~^ ERROR ambiguous use of `||` while let Range { start: _, end: _ } = true..true && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` while let Range { start: _, end: _ } = true..true || false { } - //~^ ERROR ambigious use of `||` + //~^ ERROR ambiguous use of `||` if let true = false && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` while let true = (1 == 2) && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` // The following cases are not an error as parenthesis are used to // clarify intent: diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr index 8597294913f27..411cb99fbca19 100644 --- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr @@ -1,4 +1,4 @@ -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2015.rs:21:47 | LL | if let Range { start: _, end: _ } = true..true && false { } @@ -7,7 +7,7 @@ LL | if let Range { start: _, end: _ } = true..true && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `||` +error: ambiguous use of `||` --> $DIR/syntax-ambiguity-2015.rs:24:47 | LL | if let Range { start: _, end: _ } = true..true || false { } @@ -16,7 +16,7 @@ LL | if let Range { start: _, end: _ } = true..true || false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2015.rs:27:50 | LL | while let Range { start: _, end: _ } = true..true && false { } @@ -25,7 +25,7 @@ LL | while let Range { start: _, end: _ } = true..true && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `||` +error: ambiguous use of `||` --> $DIR/syntax-ambiguity-2015.rs:30:50 | LL | while let Range { start: _, end: _ } = true..true || false { } @@ -34,7 +34,7 @@ LL | while let Range { start: _, end: _ } = true..true || false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2015.rs:33:19 | LL | if let true = false && false { } @@ -43,7 +43,7 @@ LL | if let true = false && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2015.rs:36:22 | LL | while let true = (1 == 2) && false { } diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs index baa90bcf8e971..99495717c3a89 100644 --- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs +++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs @@ -19,22 +19,22 @@ fn main() { use std::ops::Range; if let Range { start: _, end: _ } = true..true && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` if let Range { start: _, end: _ } = true..true || false { } - //~^ ERROR ambigious use of `||` + //~^ ERROR ambiguous use of `||` while let Range { start: _, end: _ } = true..true && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` while let Range { start: _, end: _ } = true..true || false { } - //~^ ERROR ambigious use of `||` + //~^ ERROR ambiguous use of `||` if let true = false && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` while let true = (1 == 2) && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` // The following cases are not an error as parenthesis are used to // clarify intent: diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr index 86ee04747b29d..bd49abeb7b247 100644 --- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr @@ -1,4 +1,4 @@ -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2018.rs:21:47 | LL | if let Range { start: _, end: _ } = true..true && false { } @@ -7,7 +7,7 @@ LL | if let Range { start: _, end: _ } = true..true && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `||` +error: ambiguous use of `||` --> $DIR/syntax-ambiguity-2018.rs:24:47 | LL | if let Range { start: _, end: _ } = true..true || false { } @@ -16,7 +16,7 @@ LL | if let Range { start: _, end: _ } = true..true || false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2018.rs:27:50 | LL | while let Range { start: _, end: _ } = true..true && false { } @@ -25,7 +25,7 @@ LL | while let Range { start: _, end: _ } = true..true && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `||` +error: ambiguous use of `||` --> $DIR/syntax-ambiguity-2018.rs:30:50 | LL | while let Range { start: _, end: _ } = true..true || false { } @@ -34,7 +34,7 @@ LL | while let Range { start: _, end: _ } = true..true || false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2018.rs:33:19 | LL | if let true = false && false { } @@ -43,7 +43,7 @@ LL | if let true = false && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2018.rs:36:22 | LL | while let true = (1 == 2) && false { } diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed b/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed index d70c847e9fe68..f13f8ef2bb4cf 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed @@ -24,7 +24,7 @@ use std::fmt::{Debug, Display}; // • one generic parameter (T) bound inline // • one parameter (T) with a where clause // • two parameters (T and U), both bound inline -// • two paramters (T and U), one bound inline, one with a where clause +// • two parameters (T and U), one bound inline, one with a where clause // • two parameters (T and U), both with where clauses // // —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1 diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives.rs b/src/test/ui/rust-2018/edition-lint-infer-outlives.rs index 0e4436fe1632f..f47b3fcb9be9a 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives.rs +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives.rs @@ -24,7 +24,7 @@ use std::fmt::{Debug, Display}; // • one generic parameter (T) bound inline // • one parameter (T) with a where clause // • two parameters (T and U), both bound inline -// • two paramters (T and U), one bound inline, one with a where clause +// • two parameters (T and U), one bound inline, one with a where clause // • two parameters (T and U), both with where clauses // // —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1 diff --git a/src/test/ui/specialization/issue-52050.rs b/src/test/ui/specialization/issue-52050.rs index 70cdb4899c421..00d8d126e0573 100644 --- a/src/test/ui/specialization/issue-52050.rs +++ b/src/test/ui/specialization/issue-52050.rs @@ -12,7 +12,7 @@ // Regression test for #52050: when inserting the blanket impl `I` // into the tree, we had to replace the child node for `Foo`, which -// led to the struture of the tree being messed up. +// led to the structure of the tree being messed up. use std::iter::Iterator; diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 69a4c09c2285d..3d5e18e37b070 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -163,7 +163,7 @@ fn check_cfgs(contents: &mut String, file: &Path, fn find_test_mod(contents: &str) -> usize { if let Some(mod_tests_idx) = contents.find("mod tests") { - // Also capture a previos line indicating "mod tests" in cfg-ed out + // Also capture a previous line indicating "mod tests" in cfg-ed out let prev_newline_idx = contents[..mod_tests_idx].rfind('\n').unwrap_or(mod_tests_idx); let prev_newline_idx = contents[..prev_newline_idx].rfind('\n'); if let Some(nl) = prev_newline_idx { From 3d9231c453a676ae298ab4e1ab2965ce77ba80da Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Tue, 23 Oct 2018 09:39:33 -0700 Subject: [PATCH 46/54] Update stdsimd submodule Fixes a SSE2 bug. --- src/stdsimd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdsimd b/src/stdsimd index 307650500de5b..431766a3fbcfb 160000 --- a/src/stdsimd +++ b/src/stdsimd @@ -1 +1 @@ -Subproject commit 307650500de5b44dc1047dc9d15e449e09d92b57 +Subproject commit 431766a3fbcfb6dafb2d5a3866c1609bf44ee554 From 320ec8137e90bf6dd13b62df033372a33f261bb8 Mon Sep 17 00:00:00 2001 From: iirelu Date: Tue, 23 Oct 2018 22:27:02 +0200 Subject: [PATCH 47/54] Hopefully fix compile error This was added in the fortnight this PR spent stale. I'm hoping this one-liner fixes it. --- src/libstd/keyword_docs.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 1e801373736c5..6c95854c66cbf 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -209,7 +209,6 @@ mod enum_keyword { } /// The mirror use case of FFI is also done via the `extern` keyword: /// /// ```rust -/// # #![allow(private_no_mangle_fns)] /// #[no_mangle] /// pub extern fn callable_from_c(x: i32) -> bool { /// x % 3 == 0 From 35391326a6e59fb80f851a8345f577a2527eae3c Mon Sep 17 00:00:00 2001 From: Son Date: Wed, 24 Oct 2018 09:28:04 +1100 Subject: [PATCH 48/54] Update comment based on suggestion. --- src/libcore/task/wake.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index c2768e70aec7b..c9fb22e0080dd 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -190,8 +190,9 @@ impl LocalWaker { impl From for Waker { /// Converts a `LocalWaker` into a `Waker`. /// - /// This conversion forgets local waker and allocates a new waker with - /// the same inner. + /// This conversion turns a `!Sync` `LocalWaker` into a `Sync` `Waker`, allowing a wakeup + /// object to be sent to another thread, but giving up its ability to do specialized + /// thread-local wakeup behavior. #[inline] fn from(local_waker: LocalWaker) -> Self { local_waker.0 From f2443a9b2005865a0e9c8b3163ec47e82d87f503 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 23 Oct 2018 15:38:31 -0700 Subject: [PATCH 49/54] Set RUST_BACKTRACE=0 for rustdoc-ui/failed-doctest-output.rs This UI test is sensitive to backtrace output, so it should make sure that backtraces are not enabled by the environment. --- src/test/rustdoc-ui/failed-doctest-output.rs | 1 + .../rustdoc-ui/failed-doctest-output.stdout | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/test/rustdoc-ui/failed-doctest-output.rs b/src/test/rustdoc-ui/failed-doctest-output.rs index 62e495288cb9b..932fe1c8eb0b2 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.rs +++ b/src/test/rustdoc-ui/failed-doctest-output.rs @@ -15,6 +15,7 @@ // compile-flags:--test // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // failure-status: 101 +// rustc-env:RUST_BACKTRACE=0 // doctest fails at runtime /// ``` diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index cf417f8d412ee..876f6c0a80b1d 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -1,22 +1,22 @@ running 2 tests -test $DIR/failed-doctest-output.rs - OtherStruct (line 26) ... FAILED -test $DIR/failed-doctest-output.rs - SomeStruct (line 20) ... FAILED +test $DIR/failed-doctest-output.rs - OtherStruct (line 27) ... FAILED +test $DIR/failed-doctest-output.rs - SomeStruct (line 21) ... FAILED failures: ----- $DIR/failed-doctest-output.rs - OtherStruct (line 26) stdout ---- +---- $DIR/failed-doctest-output.rs - OtherStruct (line 27) stdout ---- error[E0425]: cannot find value `no` in this scope - --> $DIR/failed-doctest-output.rs:27:1 + --> $DIR/failed-doctest-output.rs:28:1 | 3 | no | ^^ not found in this scope -thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:332:13 +thread '$DIR/failed-doctest-output.rs - OtherStruct (line 27)' panicked at 'couldn't compile the test', librustdoc/test.rs:332:13 note: Run with `RUST_BACKTRACE=1` for a backtrace. ----- $DIR/failed-doctest-output.rs - SomeStruct (line 20) stdout ---- -thread '$DIR/failed-doctest-output.rs - SomeStruct (line 20)' panicked at 'test executable failed: +---- $DIR/failed-doctest-output.rs - SomeStruct (line 21) stdout ---- +thread '$DIR/failed-doctest-output.rs - SomeStruct (line 21)' panicked at 'test executable failed: thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1 note: Run with `RUST_BACKTRACE=1` for a backtrace. @@ -25,8 +25,8 @@ note: Run with `RUST_BACKTRACE=1` for a backtrace. failures: - $DIR/failed-doctest-output.rs - OtherStruct (line 26) - $DIR/failed-doctest-output.rs - SomeStruct (line 20) + $DIR/failed-doctest-output.rs - OtherStruct (line 27) + $DIR/failed-doctest-output.rs - SomeStruct (line 21) test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out From 398a264a771f986e9eb3d0798e8216afe254051c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 24 Oct 2018 01:09:49 -0700 Subject: [PATCH 50/54] Update compiler-builtins submodule This commit updates our `compiler-builtins` submodule which brings in at least a few improvements for intrinsics on wasm32 --- src/libcompiler_builtins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 0703bfa72524e..f7fbdc33dfc79 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 0703bfa72524e01e414477657ca9b64794c5c1c3 +Subproject commit f7fbdc33dfc79584375985b15a183e32e33ce72d From be2075c6614532b6b58bef455c3ff89ecf2ef625 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 24 Oct 2018 12:19:47 +0200 Subject: [PATCH 51/54] This is a regression test for #54478. I confirmed that it fails on: rustdoc 1.30.0-beta.12 (96a229824 2018-10-04) and passes on: rustdoc 1.31.0-nightly (f99911a4a 2018-10-23) --- .../rustdoc/issue-54478-demo-allocator.rs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/test/rustdoc/issue-54478-demo-allocator.rs diff --git a/src/test/rustdoc/issue-54478-demo-allocator.rs b/src/test/rustdoc/issue-54478-demo-allocator.rs new file mode 100644 index 0000000000000..4811f363bc97a --- /dev/null +++ b/src/test/rustdoc/issue-54478-demo-allocator.rs @@ -0,0 +1,42 @@ +// Issue #54478: regression test showing that we can demonstrate +// `#[global_allocator]` in code blocks built by `rustdoc`. +// +// ## Background +// +// Changes in lang-item visibility injected failures that were only +// exposed when compiling with `-C prefer-dynamic`. But `rustdoc` used +// `-C prefer-dynamic` (and had done so for years, for reasons we did +// not document at that time). +// +// Rather than try to revise the visbility semanics, we instead +// decided to change `rustdoc` to behave more like the compiler's +// default setting, by leaving off `-C prefer-dynamic`. + +// compile-flags:--test + +//! This is a doc comment +//! +//! ```rust +//! use std::alloc::*; +//! +//! #[global_allocator] +//! static ALLOC: A = A; +//! +//! static mut HIT: bool = false; +//! +//! struct A; +//! +//! unsafe impl GlobalAlloc for A { +//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 { +//! HIT = true; +//! System.alloc(layout) +//! } +//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { +//! System.dealloc(ptr, layout); +//! } +//! } +//! +//! fn main() { +//! assert!(unsafe { HIT }); +//! } +//! ``` From c2463af45d1f2eb03c4b5d5ff2c8842f503832ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Wed, 24 Oct 2018 20:34:34 +0200 Subject: [PATCH 52/54] Typo --- src/librustc_mir/interpret/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 954616fe9fcd7..c28d19158a8c0 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -733,7 +733,7 @@ where // Not yet interned, so proceed recursively self.intern_static(alloc, mutability)?; } else if self.dead_alloc_map.contains_key(&alloc) { - // danging pointer + // dangling pointer return err!(ValidationFailure( "encountered dangling pointer in final constant".into(), )) From 0b82e03a88af4fccfd64a62288a9066cadc2e603 Mon Sep 17 00:00:00 2001 From: OCTronics Date: Fri, 19 Oct 2018 12:00:45 +0200 Subject: [PATCH 53/54] Documents `From` implementations for `Stdio` Add a basic summary and an example to From `ChildStdin`, `ChildStdout`, `ChildStderr`, `File` implementations. --- src/libstd/process.rs | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 58ac4e944087e..a9219f75362db 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1016,6 +1016,28 @@ impl fmt::Debug for Stdio { #[stable(feature = "stdio_from", since = "1.20.0")] impl From for Stdio { + /// Converts a `ChildStdin` into a `Stdio` + /// + /// # Examples + /// + /// `ChildStdin` will be converted to `Stdio` using `Stdio::from` under the hood. + /// + /// ```rust + /// use std::process::{Command, Stdio}; + /// + /// let reverse = Command::new("rev") + /// .stdin(Stdio::piped()) + /// .spawn() + /// .expect("failed reverse command"); + /// + /// let _echo = Command::new("echo") + /// .arg("Hello, world!") + /// .stdout(reverse.stdin.unwrap()) // Converted into a Stdio here + /// .output() + /// .expect("failed echo command"); + /// + /// // "!dlrow ,olleH" echoed to console + /// ``` fn from(child: ChildStdin) -> Stdio { Stdio::from_inner(child.into_inner().into()) } @@ -1023,6 +1045,28 @@ impl From for Stdio { #[stable(feature = "stdio_from", since = "1.20.0")] impl From for Stdio { + /// Converts a `ChildStdout` into a `Stdio` + /// + /// # Examples + /// + /// `ChildStdout` will be converted to `Stdio` using `Stdio::from` under the hood. + /// + /// ```rust + /// use std::process::{Command, Stdio}; + /// + /// let hello = Command::new("echo") + /// .arg("Hello, world!") + /// .stdout(Stdio::piped()) + /// .spawn() + /// .expect("failed echo command"); + /// + /// let reverse = Command::new("rev") + /// .stdin(hello.stdout.unwrap()) // Converted into a Stdio here + /// .output() + /// .expect("failed reverse command"); + /// + /// assert_eq!(reverse.stdout, b"!dlrow ,olleH\n"); + /// ``` fn from(child: ChildStdout) -> Stdio { Stdio::from_inner(child.into_inner().into()) } @@ -1030,6 +1074,30 @@ impl From for Stdio { #[stable(feature = "stdio_from", since = "1.20.0")] impl From for Stdio { + /// Converts a `ChildStderr` into a `Stdio` + /// + /// # Examples + /// + /// ```rust,no_run + /// use std::process::{Command, Stdio}; + /// + /// let reverse = Command::new("rev") + /// .arg("non_existing_file.txt") + /// .stderr(Stdio::piped()) + /// .spawn() + /// .expect("failed reverse command"); + /// + /// let cat = Command::new("cat") + /// .arg("-") + /// .stdin(reverse.stderr.unwrap()) // Converted into a Stdio here + /// .output() + /// .expect("failed echo command"); + /// + /// assert_eq!( + /// String::from_utf8_lossy(&cat.stdout), + /// "rev: cannot open non_existing_file.txt: No such file or directory\n" + /// ); + /// ``` fn from(child: ChildStderr) -> Stdio { Stdio::from_inner(child.into_inner().into()) } @@ -1037,6 +1105,26 @@ impl From for Stdio { #[stable(feature = "stdio_from", since = "1.20.0")] impl From for Stdio { + /// Converts a `File` into a `Stdio` + /// + /// # Examples + /// + /// `File` will be converted to `Stdio` using `Stdio::from` under the hood. + /// + /// ```rust,no_run + /// use std::fs::File; + /// use std::process::Command; + /// + /// // With the `foo.txt` file containing `Hello, world!" + /// let file = File::open("foo.txt").unwrap(); + /// + /// let reverse = Command::new("rev") + /// .stdin(file) // Implicit File convertion into a Stdio + /// .output() + /// .expect("failed reverse command"); + /// + /// assert_eq!(reverse.stdout, b"!dlrow ,olleH"); + /// ``` fn from(file: fs::File) -> Stdio { Stdio::from_inner(file.into_inner().into()) } From 538f65eb617f5d4596cf0d263e48998a70137ce1 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Wed, 24 Oct 2018 15:19:23 -0700 Subject: [PATCH 54/54] Fix doc for new copysign functions Thanks to @LukasKalbertodt for catching this. Addresses a comment raised in #55169 after it was merged. --- src/libstd/f32.rs | 8 ++++---- src/libstd/f64.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index c3f225d1eb013..7d17aaf2f261b 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -198,12 +198,12 @@ impl f32 { } } - /// Returns a number composed of the magnitude of one number and the sign of - /// another. + /// Returns a number composed of the magnitude of `self` and the sign of + /// `y`. /// /// Equal to `self` if the sign of `self` and `y` are the same, otherwise - /// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y` - /// is returned. + /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of + /// `y` is returned. /// /// # Examples /// diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index da062dda77a47..ecaaf8323ab91 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -176,12 +176,12 @@ impl f64 { } } - /// Returns a number composed of the magnitude of one number and the sign of - /// another. + /// Returns a number composed of the magnitude of `self` and the sign of + /// `y`. /// /// Equal to `self` if the sign of `self` and `y` are the same, otherwise - /// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y` - /// is returned. + /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of + /// `y` is returned. /// /// # Examples ///