diff --git a/mk/main.mk b/mk/main.mk index c5b2fc8b9531e..d25f983214235 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,12 +13,12 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=1.0.0 +CFG_RELEASE_NUM=1.1.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release # versions (section 9) -CFG_PRERELEASE_VERSION=.3 +CFG_PRERELEASE_VERSION=.1 CFG_FILENAME_EXTRA=4e7c5e5c diff --git a/src/doc/trpl/README.md b/src/doc/trpl/README.md index dfe837285c877..01ef88dde2270 100644 --- a/src/doc/trpl/README.md +++ b/src/doc/trpl/README.md @@ -24,6 +24,7 @@ is the first. After this: * [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks. * [Nightly Rust][nr] - Cutting-edge features that aren’t in stable builds yet. * [Glossary][gl] - A reference of terms used in the book. +* [Academic Research][ar] - Literature that influenced Rust. [gs]: getting-started.html [lr]: learn-rust.html @@ -31,6 +32,7 @@ is the first. After this: [ss]: syntax-and-semantics.html [nr]: nightly-rust.html [gl]: glossary.html +[ar]: academic-research.html After reading this introduction, you’ll want to dive into either ‘Learn Rust’ or ‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index a179f8fa55e5e..81a550b0f9a3d 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -55,6 +55,7 @@ * [Deref coercions](deref-coercions.md) * [Macros](macros.md) * [Raw Pointers](raw-pointers.md) + * [`unsafe`](unsafe.md) * [Nightly Rust](nightly-rust.md) * [Compiler Plugins](compiler-plugins.md) * [Inline Assembly](inline-assembly.md) diff --git a/src/doc/trpl/associated-types.md b/src/doc/trpl/associated-types.md index d59239016d881..55e2787cc2591 100644 --- a/src/doc/trpl/associated-types.md +++ b/src/doc/trpl/associated-types.md @@ -1,8 +1,8 @@ % Associated Types -Associated types are a powerful part of Rust's type system. They're related to -the idea of a 'type family', in other words, grouping multiple types together. That -description is a bit abstract, so let's dive right into an example. If you want +Associated types are a powerful part of Rust’s type system. They’re related to +the idea of a ‘type family’, in other words, grouping multiple types together. That +description is a bit abstract, so let’s dive right into an example. If you want to write a `Graph` trait, you have two types to be generic over: the node type and the edge type. So you might write a trait, `Graph`, that looks like this: @@ -48,11 +48,11 @@ fn distance(graph: &G, start: &G::N, end: &G::N) -> uint { ... } No need to deal with the `E`dge type here! -Let's go over all this in more detail. +Let’s go over all this in more detail. ## Defining associated types -Let's build that `Graph` trait. Here's the definition: +Let’s build that `Graph` trait. Here’s the definition: ```rust trait Graph { @@ -86,7 +86,7 @@ trait Graph { ## Implementing associated types Just like any trait, traits that use associated types use the `impl` keyword to -provide implementations. Here's a simple implementation of Graph: +provide implementations. Here’s a simple implementation of Graph: ```rust # trait Graph { @@ -118,13 +118,13 @@ impl Graph for MyGraph { This silly implementation always returns `true` and an empty `Vec`, but it gives you an idea of how to implement this kind of thing. We first need three `struct`s, one for the graph, one for the node, and one for the edge. If it made -more sense to use a different type, that would work as well, we're just going to +more sense to use a different type, that would work as well, we’re just going to use `struct`s for all three here. Next is the `impl` line, which is just like implementing any other trait. From here, we use `=` to define our associated types. The name the trait uses -goes on the left of the `=`, and the concrete type we're `impl`ementing this +goes on the left of the `=`, and the concrete type we’re `impl`ementing this for goes on the right. Finally, we use the concrete types in our function declarations. diff --git a/src/doc/trpl/casting-between-types.md b/src/doc/trpl/casting-between-types.md index 90731b64a38dc..f0c673b561a0e 100644 --- a/src/doc/trpl/casting-between-types.md +++ b/src/doc/trpl/casting-between-types.md @@ -33,7 +33,7 @@ let b = a as u32; // four eights makes 32 It’s a ‘non-scalar cast’ because we have multiple values here: the four elements of the array. These kinds of casts are very dangerous, because they -make assumptions about the way that multiple underlying strucutres are +make assumptions about the way that multiple underlying structures are implemented. For this, we need something more dangerous. # `transmute` @@ -59,7 +59,7 @@ unsafe { } ``` -We have to wrap the operation in an `unsafe` block, but this will compile +We have to wrap the operation in an `unsafe` block for this to compile successfully. Technically, only the `mem::transmute` call itself needs to be in the block, but it's nice in this case to enclose everything related, so you know where to look. In this case, the details about `a` are also important, and diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index e3de8eb30be91..604dcb739df63 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -1,9 +1,9 @@ % Closures Rust not only has named functions, but anonymous functions as well. Anonymous -functions that have an associated environment are called 'closures', because they +functions that have an associated environment are called ‘closures’, because they close over an environment. Rust has a really great implementation of them, as -we'll see. +we’ll see. # Syntax @@ -15,7 +15,7 @@ let plus_one = |x: i32| x + 1; assert_eq!(2, plus_one(1)); ``` -We create a binding, `plus_one`, and assign it to a closure. The closure's +We create a binding, `plus_one`, and assign it to a closure. The closure’s arguments go between the pipes (`|`), and the body is an expression, in this case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line closures too: @@ -33,7 +33,7 @@ let plus_two = |x| { assert_eq!(4, plus_two(2)); ``` -You'll notice a few things about closures that are a bit different than regular +You’ll notice a few things about closures that are a bit different than regular functions defined with `fn`. The first of which is that we did not need to annotate the types of arguments the closure takes or the values it returns. We can: @@ -44,13 +44,13 @@ let plus_one = |x: i32| -> i32 { x + 1 }; assert_eq!(2, plus_one(1)); ``` -But we don't have to. Why is this? Basically, it was chosen for ergonomic reasons. +But we don’t have to. Why is this? Basically, it was chosen for ergonomic reasons. While specifying the full type for named functions is helpful with things like documentation and type inference, the types of closures are rarely documented since they’re anonymous, and they don’t cause the kinds of error-at-a-distance that inferring named function types can. -The second is that the syntax is similar, but a bit different. I've added spaces +The second is that the syntax is similar, but a bit different. I’ve added spaces here to make them look a little closer: ```rust @@ -59,11 +59,11 @@ let plus_one_v2 = |x: i32 | -> i32 { x + 1 }; let plus_one_v3 = |x: i32 | x + 1 ; ``` -Small differences, but they're similar in ways. +Small differences, but they’re similar in ways. # Closures and their environment -Closures are called such because they 'close over their environment.' It +Closures are called such because they ‘close over their environment’. It looks like this: ```rust @@ -105,7 +105,7 @@ fn main() { ^ ``` -A verbose yet helpful error message! As it says, we can't take a mutable borrow +A verbose yet helpful error message! As it says, we can’t take a mutable borrow on `num` because the closure is already borrowing it. If we let the closure go out of scope, we can: @@ -140,7 +140,7 @@ let takes_nums = || nums; ``` `Vec` has ownership over its contents, and therefore, when we refer to it -in our closure, we have to take ownership of `nums`. It's the same as if we'd +in our closure, we have to take ownership of `nums`. It’s the same as if we’d passed `nums` to a function that took ownership of it. ## `move` closures @@ -156,7 +156,7 @@ let owns_num = move |x: i32| x + num; Now, even though the keyword is `move`, the variables follow normal move semantics. In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy -of `num`. So what's the difference? +of `num`. So what’s the difference? ```rust let mut num = 5; @@ -171,11 +171,11 @@ assert_eq!(10, num); ``` So in this case, our closure took a mutable reference to `num`, and then when -we called `add_num`, it mutated the underlying value, as we'd expect. We also +we called `add_num`, it mutated the underlying value, as we’d expect. We also needed to declare `add_num` as `mut` too, because we’re mutating its environment. -If we change to a `move` closure, it's different: +If we change to a `move` closure, it’s different: ```rust let mut num = 5; @@ -203,8 +203,8 @@ you tons of control over what your code does, and closures are no different. # Closure implementation -Rust's implementation of closures is a bit different than other languages. They -are effectively syntax sugar for traits. You'll want to make sure to have read +Rust’s implementation of closures is a bit different than other languages. They +are effectively syntax sugar for traits. You’ll want to make sure to have read the [traits chapter][traits] before this one, as well as the chapter on [trait objects][trait-objects]. @@ -237,9 +237,9 @@ pub trait FnOnce { # } ``` -You'll notice a few differences between these traits, but a big one is `self`: +You’ll notice a few differences between these traits, but a big one is `self`: `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This -covers all three kinds of `self` via the usual method call syntax. But we've +covers all three kinds of `self` via the usual method call syntax. But we’ve split them up into three traits, rather than having a single one. This gives us a large amount of control over what kind of closures we can take. @@ -253,7 +253,7 @@ Now that we know that closures are traits, we already know how to accept and return closures: just like any other trait! This also means that we can choose static vs dynamic dispatch as well. First, -let's write a function which takes something callable, calls it, and returns +let’s write a function which takes something callable, calls it, and returns the result: ```rust @@ -271,7 +271,7 @@ assert_eq!(3, answer); We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it suggests: it calls the closure, giving it `1` as an argument. -Let's examine the signature of `call_with_one` in more depth: +Let’s examine the signature of `call_with_one` in more depth: ```rust fn call_with_one(some_closure: F) -> i32 @@ -280,7 +280,7 @@ fn call_with_one(some_closure: F) -> i32 ``` We take one parameter, and it has the type `F`. We also return a `i32`. This part -isn't interesting. The next part is: +isn’t interesting. The next part is: ```rust # fn call_with_one(some_closure: F) -> i32 @@ -292,9 +292,9 @@ Because `Fn` is a trait, we can bound our generic with it. In this case, our clo takes a `i32` as an argument and returns an `i32`, and so the generic bound we use is `Fn(i32) -> i32`. -There's one other key point here: because we're bounding a generic with a -trait, this will get monomorphized, and therefore, we'll be doing static -dispatch into the closure. That's pretty neat. In many langauges, closures are +There’s one other key point here: because we’re bounding a generic with a +trait, this will get monomorphized, and therefore, we’ll be doing static +dispatch into the closure. That’s pretty neat. In many langauges, closures are inherently heap allocated, and will always involve dynamic dispatch. In Rust, we can stack allocate our closure environment, and statically dispatch the call. This happens quite often with iterators and their adapters, which often @@ -320,7 +320,7 @@ to our closure when we pass it to `call_with_one`, so we use `&||`. It’s very common for functional-style code to return closures in various situations. If you try to return a closure, you may run into an error. At -first, it may seem strange, but we'll figure it out. Here's how you'd probably +first, it may seem strange, but we’ll figure it out. Here’s how you’d probably try to return a closure from a function: ```rust,ignore @@ -361,7 +361,7 @@ In order to return something from a function, Rust needs to know what size the return type is. But since `Fn` is a trait, it could be various things of various sizes: many different types can implement `Fn`. An easy way to give something a size is to take a reference to it, as references -have a known size. So we'd write this: +have a known size. So we’d write this: ```rust,ignore fn factory() -> &(Fn(i32) -> Vec) { @@ -385,7 +385,7 @@ fn factory() -> &(Fn(i32) -> i32) { ``` Right. Because we have a reference, we need to give it a lifetime. But -our `factory()` function takes no arguments, so elision doesn't kick in +our `factory()` function takes no arguments, so elision doesn’t kick in here. What lifetime can we choose? `'static`: ```rust,ignore @@ -414,7 +414,7 @@ error: mismatched types: ``` -This error is letting us know that we don't have a `&'static Fn(i32) -> i32`, +This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`, we have a `[closure :7:9: 7:20]`. Wait, what? Because each closure generates its own environment `struct` and implementation @@ -422,7 +422,7 @@ of `Fn` and friends, these types are anonymous. They exist just solely for this closure. So Rust shows them as `closure `, rather than some autogenerated name. -But why doesn't our closure implement `&'static Fn`? Well, as we discussed before, +But why doesn’t our closure implement `&'static Fn`? Well, as we discussed before, closures borrow their environment. And in this case, our environment is based on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime of the stack frame. So if we returned this closure, the function call would be @@ -445,7 +445,7 @@ assert_eq!(6, answer); # } ``` -We use a trait object, by `Box`ing up the `Fn`. There's just one last problem: +We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem: ```text error: `num` does not live long enough @@ -471,5 +471,5 @@ assert_eq!(6, answer); ``` By making the inner closure a `move Fn`, we create a new stack frame for our -closure. By `Box`ing it up, we've given it a known size, and allowing it to +closure. By `Box`ing it up, we’ve given it a known size, and allowing it to escape our stack frame. diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md index 83e8cc629fd5e..3ab3401e61264 100644 --- a/src/doc/trpl/crates-and-modules.md +++ b/src/doc/trpl/crates-and-modules.md @@ -1,16 +1,16 @@ % Crates and Modules -When a project starts getting large, it's considered good software +When a project starts getting large, it’s considered good software engineering practice to split it up into a bunch of smaller pieces, and then -fit them together. It's also important to have a well-defined interface, so +fit them together. It’s also important to have a well-defined interface, so that some of your functionality is private, and some is public. To facilitate these kinds of things, Rust has a module system. # Basic terminology: Crates and Modules -Rust has two distinct terms that relate to the module system: *crate* and -*module*. A crate is synonymous with a *library* or *package* in other -languages. Hence "Cargo" as the name of Rust's package management tool: you +Rust has two distinct terms that relate to the module system: ‘crate’ and +‘module’. A crate is synonymous with a ‘library’ or ‘package’ in other +languages. Hence “Cargo” as the name of Rust’s package management tool: you ship your crates to others with Cargo. Crates can produce an executable or a library, depending on the project. @@ -18,10 +18,10 @@ Each crate has an implicit *root module* that contains the code for that crate. You can then define a tree of sub-modules under that root module. Modules allow you to partition your code within the crate itself. -As an example, let's make a *phrases* crate, which will give us various phrases -in different languages. To keep things simple, we'll stick to "greetings" and -"farewells" as two kinds of phrases, and use English and Japanese (日本語) as -two languages for those phrases to be in. We'll use this module layout: +As an example, let’s make a *phrases* crate, which will give us various phrases +in different languages. To keep things simple, we’ll stick to ‘greetings’ and +‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as +two languages for those phrases to be in. We’ll use this module layout: ```text +-----------+ @@ -47,7 +47,7 @@ In this example, `phrases` is the name of our crate. All of the rest are modules. You can see that they form a tree, branching out from the crate *root*, which is the root of the tree: `phrases` itself. -Now that we have a plan, let's define these modules in code. To start, +Now that we have a plan, let’s define these modules in code. To start, generate a new crate with Cargo: ```bash @@ -72,7 +72,7 @@ above. # Defining Modules -To define each of our modules, we use the `mod` keyword. Let's make our +To define each of our modules, we use the `mod` keyword. Let’s make our `src/lib.rs` look like this: ``` @@ -101,7 +101,7 @@ Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules with double-colon (`::`) notation: our four nested modules are `english::greetings`, `english::farewells`, `japanese::greetings`, and `japanese::farewells`. Because these sub-modules are namespaced under their -parent module, the names don't conflict: `english::greetings` and +parent module, the names don’t conflict: `english::greetings` and `japanese::greetings` are distinct, even though their names are both `greetings`. @@ -116,11 +116,11 @@ build deps examples libphrases-a7448e02a0468eaa.rlib native ``` `libphrase-hash.rlib` is the compiled crate. Before we see how to use this -crate from another crate, let's break it up into multiple files. +crate from another crate, let’s break it up into multiple files. # Multiple file crates -If each crate were just one file, these files would get very large. It's often +If each crate were just one file, these files would get very large. It’s often easier to split up crates into multiple files, and Rust supports this in two ways. @@ -141,7 +141,7 @@ mod english; If we do that, Rust will expect to find either a `english.rs` file, or a `english/mod.rs` file with the contents of our module. -Note that in these files, you don't need to re-declare the module: that's +Note that in these files, you don’t need to re-declare the module: that’s already been done with the initial `mod` declaration. Using these two techniques, we can break up our crate into two directories and @@ -180,7 +180,7 @@ mod japanese; These two declarations tell Rust to look for either `src/english.rs` and `src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending -on our preference. In this case, because our modules have sub-modules, we've +on our preference. In this case, because our modules have sub-modules, we’ve chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look like this: @@ -192,11 +192,11 @@ mod farewells; Again, these declarations tell Rust to look for either `src/english/greetings.rs` and `src/japanese/greetings.rs` or `src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because -these sub-modules don't have their own sub-modules, we've chosen to make them +these sub-modules don’t have their own sub-modules, we’ve chosen to make them `src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew! The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are -both empty at the moment. Let's add some functions. +both empty at the moment. Let’s add some functions. Put this in `src/english/greetings.rs`: @@ -223,7 +223,7 @@ fn hello() -> String { ``` Of course, you can copy and paste this from this web page, or just type -something else. It's not important that you actually put "konnichiwa" to learn +something else. It’s not important that you actually put ‘konnichiwa’ to learn about the module system. Put this in `src/japanese/farewells.rs`: @@ -234,17 +234,17 @@ fn goodbye() -> String { } ``` -(This is "Sayōnara", if you're curious.) +(This is ‘Sayōnara’, if you’re curious.) -Now that we have some functionality in our crate, let's try to use it from +Now that we have some functionality in our crate, let’s try to use it from another crate. # Importing External Crates -We have a library crate. Let's make an executable crate that imports and uses +We have a library crate. Let’s make an executable crate that imports and uses our library. -Make a `src/main.rs` and put this in it (it won't quite compile yet): +Make a `src/main.rs` and put this in it (it won’t quite compile yet): ```rust,ignore extern crate phrases; @@ -259,7 +259,7 @@ fn main() { ``` The `extern crate` declaration tells Rust that we need to compile and link to -the `phrases` crate. We can then use `phrases`' modules in this one. As we +the `phrases` crate. We can then use `phrases`’ modules in this one. As we mentioned earlier, you can use double colons to refer to sub-modules and the functions inside of them. @@ -267,10 +267,10 @@ Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate, rather than a library crate. Our package now has two crates: `src/lib.rs` and `src/main.rs`. This pattern is quite common for executable crates: most functionality is in a library crate, and the executable crate uses that -library. This way, other programs can also use the library crate, and it's also +library. This way, other programs can also use the library crate, and it’s also a nice separation of concerns. -This doesn't quite work yet, though. We get four errors that look similar to +This doesn’t quite work yet, though. We get four errors that look similar to this: ```bash @@ -287,14 +287,14 @@ note: in expansion of format_args! phrases/src/main.rs:4:5: 4:76 note: expansion site ``` -By default, everything is private in Rust. Let's talk about this in some more +By default, everything is private in Rust. Let’s talk about this in some more depth. # Exporting a Public Interface Rust allows you to precisely control which aspects of your interface are public, and so private is the default. To make things public, you use the `pub` -keyword. Let's focus on the `english` module first, so let's reduce our `src/main.rs` +keyword. Let’s focus on the `english` module first, so let’s reduce our `src/main.rs` to just this: ```{rust,ignore} @@ -306,21 +306,21 @@ fn main() { } ``` -In our `src/lib.rs`, let's add `pub` to the `english` module declaration: +In our `src/lib.rs`, let’s add `pub` to the `english` module declaration: ```{rust,ignore} pub mod english; mod japanese; ``` -And in our `src/english/mod.rs`, let's make both `pub`: +And in our `src/english/mod.rs`, let’s make both `pub`: ```{rust,ignore} pub mod greetings; pub mod farewells; ``` -In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration: +In our `src/english/greetings.rs`, let’s add `pub` to our `fn` declaration: ```{rust,ignore} pub fn hello() -> String { @@ -358,12 +358,12 @@ Goodbye in English: Goodbye. Now that our functions are public, we can use them. Great! However, typing out `phrases::english::greetings::hello()` is very long and repetitive. Rust has another keyword for importing names into the current scope, so that you can -refer to them with shorter names. Let's talk about `use`. +refer to them with shorter names. Let’s talk about `use`. # Importing Modules with `use` Rust has a `use` keyword, which allows us to import names into our local scope. -Let's change our `src/main.rs` to look like this: +Let’s change our `src/main.rs` to look like this: ```{rust,ignore} extern crate phrases; @@ -378,7 +378,7 @@ fn main() { ``` The two `use` lines import each module into the local scope, so we can refer to -the functions by a much shorter name. By convention, when importing functions, it's +the functions by a much shorter name. By convention, when importing functions, it’s considered best practice to import the module, rather than the function directly. In other words, you _can_ do this: @@ -395,7 +395,7 @@ fn main() { ``` But it is not idiomatic. This is significantly more likely to introduce a -naming conflict. In our short program, it's not a big deal, but as it grows, it +naming conflict. In our short program, it’s not a big deal, but as it grows, it becomes a problem. If we have conflicting names, Rust will give a compilation error. For example, if we made the `japanese` functions public, and tried to do this: @@ -423,7 +423,7 @@ error: aborting due to previous error Could not compile `phrases`. ``` -If we're importing multiple names from the same module, we don't have to type it out +If we’re importing multiple names from the same module, we don’t have to type it out twice. Instead of this: ```{rust,ignore} @@ -439,11 +439,11 @@ use phrases::english::{greetings, farewells}; ## Re-exporting with `pub use` -You don't just use `use` to shorten identifiers. You can also use it inside of your crate +You don’t just use `use` to shorten identifiers. You can also use it inside of your crate to re-export a function inside another module. This allows you to present an external interface that may not directly map to your internal code organization. -Let's look at an example. Modify your `src/main.rs` to read like this: +Let’s look at an example. Modify your `src/main.rs` to read like this: ```{rust,ignore} extern crate phrases; @@ -494,11 +494,11 @@ mod farewells; ``` The `pub use` declaration brings the function into scope at this part of our -module hierarchy. Because we've `pub use`d this inside of our `japanese` +module hierarchy. Because we’ve `pub use`d this inside of our `japanese` module, we now have a `phrases::japanese::hello()` function and a `phrases::japanese::goodbye()` function, even though the code for them lives in `phrases::japanese::greetings::hello()` and -`phrases::japanese::farewells::goodbye()`. Our internal organization doesn't +`phrases::japanese::farewells::goodbye()`. Our internal organization doesn’t define our external interface. Here we have a `pub use` for each function we want to bring into the @@ -507,13 +507,13 @@ everything from `greetings` into the current scope: `pub use self::greetings::*` What about the `self`? Well, by default, `use` declarations are absolute paths, starting from your crate root. `self` makes that path relative to your current -place in the hierarchy instead. There's one more special form of `use`: you can +place in the hierarchy instead. There’s one more special form of `use`: you can `use super::` to reach one level up the tree from your current location. Some -people like to think of `self` as `.` and `super` as `..`, from many shells' +people like to think of `self` as `.` and `super` as `..`, from many shells’ display for the current directory and the parent directory. Outside of `use`, paths are relative: `foo::bar()` refers to a function inside -of `foo` relative to where we are. If that's prefixed with `::`, as in +of `foo` relative to where we are. If that’s prefixed with `::`, as in `::foo::bar()`, it refers to a different `foo`, an absolute path from your crate root. diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index 1d4452754baa2..9fa870ab1ac7c 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -1,20 +1,20 @@ % Macros -By now you've learned about many of the tools Rust provides for abstracting and +By now you’ve learned about many of the tools Rust provides for abstracting and reusing code. These units of code reuse have a rich semantic structure. For example, functions have a type signature, type parameters have trait bounds, and overloaded functions must belong to a particular trait. -This structure means that Rust's core abstractions have powerful compile-time +This structure means that Rust’s core abstractions have powerful compile-time correctness checking. But this comes at the price of reduced flexibility. If -you visually identify a pattern of repeated code, you may find it's difficult +you visually identify a pattern of repeated code, you may find it’s difficult or cumbersome to express that pattern as a generic function, a trait, or -anything else within Rust's semantics. +anything else within Rust’s semantics. -Macros allow us to abstract at a *syntactic* level. A macro invocation is +Macros allow us to abstract at a syntactic level. A macro invocation is shorthand for an "expanded" syntactic form. This expansion happens early in compilation, before any static checking. As a result, macros can capture many -patterns of code reuse that Rust's core abstractions cannot. +patterns of code reuse that Rust’s core abstractions cannot. The drawback is that macro-based code can be harder to understand, because fewer of the built-in rules apply. Like an ordinary function, a well-behaved @@ -23,8 +23,8 @@ difficult to design a well-behaved macro! Additionally, compiler errors in macro code are harder to interpret, because they describe problems in the expanded code, not the source-level form that developers use. -These drawbacks make macros something of a "feature of last resort". That's not -to say that macros are bad; they are part of Rust because sometimes they're +These drawbacks make macros something of a "feature of last resort". That’s not +to say that macros are bad; they are part of Rust because sometimes they’re needed for truly concise, well-abstracted code. Just keep this tradeoff in mind. @@ -40,7 +40,7 @@ let x: Vec = vec![1, 2, 3]; # assert_eq!(x, [1, 2, 3]); ``` -This can't be an ordinary function, because it takes any number of arguments. +This can’t be an ordinary function, because it takes any number of arguments. But we can imagine it as syntactic shorthand for ```rust @@ -77,20 +77,20 @@ macro_rules! vec { # } ``` -Whoa, that's a lot of new syntax! Let's break it down. +Whoa, that’s a lot of new syntax! Let’s break it down. ```ignore macro_rules! vec { ... } ``` -This says we're defining a macro named `vec`, much as `fn vec` would define a -function named `vec`. In prose, we informally write a macro's name with an +This says we’re defining a macro named `vec`, much as `fn vec` would define a +function named `vec`. In prose, we informally write a macro’s name with an exclamation point, e.g. `vec!`. The exclamation point is part of the invocation syntax and serves to distinguish a macro from an ordinary function. ## Matching -The macro is defined through a series of *rules*, which are pattern-matching +The macro is defined through a series of rules, which are pattern-matching cases. Above, we had ```ignore @@ -99,13 +99,13 @@ cases. Above, we had This is like a `match` expression arm, but the matching happens on Rust syntax trees, at compile time. The semicolon is optional on the last (here, only) -case. The "pattern" on the left-hand side of `=>` is known as a *matcher*. +case. The "pattern" on the left-hand side of `=>` is known as a ‘matcher’. These have [their own little grammar] within the language. [their own little grammar]: ../reference.html#macros The matcher `$x:expr` will match any Rust expression, binding that syntax tree -to the *metavariable* `$x`. The identifier `expr` is a *fragment specifier*; +to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’; the full possibilities are enumerated in the [advanced macros chapter][]. Surrounding the matcher with `$(...),*` will match zero or more expressions, separated by commas. @@ -158,8 +158,8 @@ Each matched expression `$x` will produce a single `push` statement in the macro expansion. The repetition in the expansion proceeds in "lockstep" with repetition in the matcher (more on this in a moment). -Because `$x` was already declared as matching an expression, we don't repeat -`:expr` on the right-hand side. Also, we don't include a separating comma as +Because `$x` was already declared as matching an expression, we don’t repeat +`:expr` on the right-hand side. Also, we don’t include a separating comma as part of the repetition operator. Instead, we have a terminating semicolon within the repeated block. @@ -180,7 +180,7 @@ The outer braces are part of the syntax of `macro_rules!`. In fact, you can use The inner braces are part of the expanded syntax. Remember, the `vec!` macro is used in an expression context. To write an expression with multiple statements, including `let`-bindings, we use a block. If your macro expands to a single -expression, you don't need this extra layer of braces. +expression, you don’t need this extra layer of braces. Note that we never *declared* that the macro produces an expression. In fact, this is not determined until we use the macro as an expression. With care, you @@ -194,7 +194,7 @@ The repetition operator follows two principal rules: 1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s it contains, in lockstep, and 2. each `$name` must be under at least as many `$(...)*`s as it was matched - against. If it is under more, it'll be duplicated, as appropriate. + against. If it is under more, it’ll be duplicated, as appropriate. This baroque macro illustrates the duplication of variables from outer repetition levels. @@ -219,7 +219,7 @@ fn main() { } ``` -That's most of the matcher syntax. These examples use `$(...)*`, which is a +That’s most of the matcher syntax. These examples use `$(...)*`, which is a "zero or more" match. Alternatively you can write `$(...)+` for a "one or more" match. Both forms optionally include a separator, which can be any token except `+` or `*`. @@ -244,9 +244,9 @@ int main() { ``` After expansion we have `5 * 2 + 3`, and multiplication has greater precedence -than addition. If you've used C macros a lot, you probably know the standard +than addition. If you’ve used C macros a lot, you probably know the standard idioms for avoiding this problem, as well as five or six others. In Rust, we -don't have to worry about it. +don’t have to worry about it. ```rust macro_rules! five_times { @@ -261,8 +261,8 @@ fn main() { The metavariable `$x` is parsed as a single expression node, and keeps its place in the syntax tree even after substitution. -Another common problem in macro systems is *variable capture*. Here's a C -macro, using [a GNU C extension] to emulate Rust's expression blocks. +Another common problem in macro systems is ‘variable capture’. Here’s a C +macro, using [a GNU C extension] to emulate Rust’s expression blocks. [a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html @@ -275,7 +275,7 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks. }) ``` -Here's a simple use case that goes terribly wrong: +Here’s a simple use case that goes terribly wrong: ```text const char *state = "reticulating splines"; @@ -315,10 +315,10 @@ fn main() { ``` This works because Rust has a [hygienic macro system][]. Each macro expansion -happens in a distinct *syntax context*, and each variable is tagged with the -syntax context where it was introduced. It's as though the variable `state` +happens in a distinct ‘syntax context’, and each variable is tagged with the +syntax context where it was introduced. It’s as though the variable `state` inside `main` is painted a different "color" from the variable `state` inside -the macro, and therefore they don't conflict. +the macro, and therefore they don’t conflict. [hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro @@ -336,7 +336,7 @@ fn main() { } ``` -Instead you need to pass the variable name into the invocation, so it's tagged +Instead you need to pass the variable name into the invocation, so it’s tagged with the right syntax context. ```rust @@ -368,7 +368,7 @@ fn main() { # Recursive macros -A macro's expansion can include more macro invocations, including invocations +A macro’s expansion can include more macro invocations, including invocations of the very same macro being expanded. These recursive macros are useful for processing tree-structured input, as illustrated by this (simplistic) HTML shorthand: @@ -429,7 +429,7 @@ they are unstable and require feature gates. Even when Rust code contains un-expanded macros, it can be parsed as a full [syntax tree][ast]. This property can be very useful for editors and other tools that process code. It also has a few consequences for the design of -Rust's macro system. +Rust’s macro system. [ast]: glossary.html#abstract-syntax-tree @@ -454,13 +454,13 @@ consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces must be balanced within a macro invocation. For example, `foo!([)` is forbidden. This allows Rust to know where the macro invocation ends. -More formally, the macro invocation body must be a sequence of *token trees*. +More formally, the macro invocation body must be a sequence of ‘token trees’. A token tree is defined recursively as either * a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or * any other single token. -Within a matcher, each metavariable has a *fragment specifier*, identifying +Within a matcher, each metavariable has a ‘fragment specifier’, identifying which syntactic form it matches. * `ident`: an identifier. Examples: `x`; `foo`. @@ -482,7 +482,7 @@ There are additional rules regarding the next token after a metavariable: * `pat` variables must be followed by one of: `=> , =` * Other variables may be followed by any token. -These rules provide some flexibility for Rust's syntax to evolve without +These rules provide some flexibility for Rust’s syntax to evolve without breaking existing macros. The macro system does not deal with parse ambiguity at all. For example, the @@ -500,7 +500,7 @@ One downside is that scoping works differently for macros, compared to other constructs in the language. Definition and expansion of macros both happen in a single depth-first, -lexical-order traversal of a crate's source. So a macro defined at module scope +lexical-order traversal of a crate’s source. So a macro defined at module scope is visible to any subsequent code in the same module, which includes the body of any subsequent child `mod` items. @@ -508,8 +508,8 @@ A macro defined within the body of a single `fn`, or anywhere else not at module scope, is visible only within that item. If a module has the `macro_use` attribute, its macros are also visible in its -parent module after the child's `mod` item. If the parent also has `macro_use` -then the macros will be visible in the grandparent after the parent's `mod` +parent module after the child’s `mod` item. If the parent also has `macro_use` +then the macros will be visible in the grandparent after the parent’s `mod` item, and so forth. The `macro_use` attribute can also appear on `extern crate`. In this context @@ -524,7 +524,7 @@ If the attribute is given simply as `#[macro_use]`, all macros are loaded. If there is no `#[macro_use]` attribute then no macros are loaded. Only macros defined with the `#[macro_export]` attribute may be loaded. -To load a crate's macros *without* linking it into the output, use `#[no_link]` +To load a crate’s macros without linking it into the output, use `#[no_link]` as well. An example: @@ -619,12 +619,12 @@ only appear at the root of your crate, not inside `mod`. This ensures that The introductory chapter mentioned recursive macros, but it did not give the full story. Recursive macros are useful for another reason: Each recursive -invocation gives you another opportunity to pattern-match the macro's +invocation gives you another opportunity to pattern-match the macro’s arguments. As an extreme example, it is possible, though hardly advisable, to implement the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton -within Rust's macro system. +within Rust’s macro system. ```rust macro_rules! bct { @@ -765,9 +765,9 @@ as `unimplemented!` until you’re ready to write them. # Procedural macros -If Rust's macro system can't do what you need, you may want to write a +If Rust’s macro system can’t do what you need, you may want to write a [compiler plugin](plugins.html) instead. Compared to `macro_rules!` macros, this is significantly more work, the interfaces are much less stable, and bugs can be much harder to track down. In exchange you get the flexibility of running arbitrary Rust code within the compiler. Syntax -extension plugins are sometimes called *procedural macros* for this reason. +extension plugins are sometimes called ‘procedural macros’ for this reason. diff --git a/src/doc/trpl/primitive-types.md b/src/doc/trpl/primitive-types.md index 811080cd50987..e4af03869d1d8 100644 --- a/src/doc/trpl/primitive-types.md +++ b/src/doc/trpl/primitive-types.md @@ -168,6 +168,7 @@ like arrays: ```rust let a = [0, 1, 2, 3, 4]; let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 +let complete = &a[..]; // A slice containing all of the elements in a ``` Slices have type `&[T]`. We’ll talk about that `T` when we cover diff --git a/src/doc/trpl/structs.md b/src/doc/trpl/structs.md index ff249d6043c10..fcf928e427c25 100644 --- a/src/doc/trpl/structs.md +++ b/src/doc/trpl/structs.md @@ -87,3 +87,33 @@ fn main() { point.y = 6; // this causes an error } ``` + +# Update syntax + +A `struct` can include `..` to indicate that you want to use a copy of some +other struct for some of the values. For example: + +```rust +struct Point3d { + x: i32, + y: i32, + z: i32, +} + +let mut point = Point3d { x: 0, y: 0, z: 0 }; +point = Point3d { y: 1, .. point }; +``` + +This gives `point` a new `y`, but keeps the old `x` and `z` values. It doesn’t +have to be the same `struct` either, you can use this syntax when making new +ones, and it will copy the values you don’t specify: + +```rust +# struct Point3d { +# x: i32, +# y: i32, +# z: i32, +# } +let origin = Point3d { x: 0, y: 0, z: 0 }; +let point = Point3d { z: 1, x: 2, .. origin }; +``` diff --git a/src/doc/trpl/trait-objects.md b/src/doc/trpl/trait-objects.md index d008d30597fea..52f8cb335a93a 100644 --- a/src/doc/trpl/trait-objects.md +++ b/src/doc/trpl/trait-objects.md @@ -1,15 +1,15 @@ % Trait Objects When code involves polymorphism, there needs to be a mechanism to determine -which specific version is actually run. This is called 'dispatch.' There are +which specific version is actually run. This is called ‘dispatch’. There are two major forms of dispatch: static dispatch and dynamic dispatch. While Rust favors static dispatch, it also supports dynamic dispatch through a mechanism -called 'trait objects.' +called ‘trait objects’. ## Background -For the rest of this chapter, we'll need a trait and some implementations. -Let's make a simple one, `Foo`. It has one method that is expected to return a +For the rest of this chapter, we’ll need a trait and some implementations. +Let’s make a simple one, `Foo`. It has one method that is expected to return a `String`. ```rust @@ -18,7 +18,7 @@ trait Foo { } ``` -We'll also implement this trait for `u8` and `String`: +We’ll also implement this trait for `u8` and `String`: ```rust # trait Foo { fn method(&self) -> String; } @@ -53,7 +53,7 @@ fn main() { } ``` -Rust uses 'monomorphization' to perform static dispatch here. This means that +Rust uses ‘monomorphization’ to perform static dispatch here. This means that Rust will create a special version of `do_something()` for both `u8` and `String`, and then replace the call sites with calls to these specialized functions. In other words, Rust generates something like this: @@ -82,7 +82,7 @@ fn main() { This has a great upside: static dispatch allows function calls to be inlined because the callee is known at compile time, and inlining is the key to good optimization. Static dispatch is fast, but it comes at -a tradeoff: 'code bloat', due to many copies of the same function +a tradeoff: ‘code bloat’, due to many copies of the same function existing in the binary, one for each type. Furthermore, compilers aren’t perfect and may “optimize” code to become slower. @@ -99,7 +99,7 @@ reason. ## Dynamic dispatch -Rust provides dynamic dispatch through a feature called 'trait objects.' Trait +Rust provides dynamic dispatch through a feature called ‘trait objects’. Trait objects, like `&Foo` or `Box`, are normal values that store a value of *any* type that implements the given trait, where the precise type can only be known at runtime. @@ -109,12 +109,12 @@ implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it (e.g. using `&x` as an argument to a function that takes `&Foo`). These trait object coercions and casts also work for pointers like `&mut T` to -`&mut Foo` and `Box` to `Box`, but that's all at the moment. Coercions +`&mut Foo` and `Box` to `Box`, but that’s all at the moment. Coercions and casts are identical. -This operation can be seen as "erasing" the compiler's knowledge about the +This operation can be seen as ‘erasing’ the compiler’s knowledge about the specific type of the pointer, and hence trait objects are sometimes referred to -as "type erasure". +as ‘type erasure’. Coming back to the example above, we can use the same trait to perform dynamic dispatch with trait objects by casting: @@ -167,7 +167,7 @@ on the heap to store it. For `Foo`, we would need to have a value that could be at least either a `String` (24 bytes) or a `u8` (1 byte), as well as any other type for which -dependent crates may implement `Foo` (any number of bytes at all). There's no +dependent crates may implement `Foo` (any number of bytes at all). There’s no way to guarantee that this last point can work if the values are stored without a pointer, because those other types can be arbitrarily large. @@ -177,14 +177,14 @@ when we are tossing a trait object around, only the size of the pointer itself. ### Representation The methods of the trait can be called on a trait object via a special record -of function pointers traditionally called a 'vtable' (created and managed by +of function pointers traditionally called a ‘vtable’ (created and managed by the compiler). Trait objects are both simple and complicated: their core representation and layout is quite straight-forward, but there are some curly error messages and surprising behaviors to discover. -Let's start simple, with the runtime representation of a trait object. The +Let’s start simple, with the runtime representation of a trait object. The `std::raw` module contains structs with layouts that are the same as the complicated built-in types, [including trait objects][stdraw]: @@ -199,12 +199,12 @@ pub struct TraitObject { [stdraw]: ../std/raw/struct.TraitObject.html -That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable" +That is, a trait object like `&Foo` consists of a ‘data’ pointer and a ‘vtable’ pointer. The data pointer addresses the data (of some unknown type `T`) that the trait -object is storing, and the vtable pointer points to the vtable ("virtual method -table") corresponding to the implementation of `Foo` for `T`. +object is storing, and the vtable pointer points to the vtable (‘virtual method +table’) corresponding to the implementation of `Foo` for `T`. A vtable is essentially a struct of function pointers, pointing to the concrete @@ -212,7 +212,7 @@ piece of machine code for each method in the implementation. A method call like `trait_object.method()` will retrieve the correct pointer out of the vtable and then do a dynamic call of it. For example: -```{rust,ignore} +```rust,ignore struct FooVtable { destructor: fn(*mut ()), size: usize, @@ -261,7 +261,7 @@ static Foo_for_String_vtable: FooVtable = FooVtable { ``` The `destructor` field in each vtable points to a function that will clean up -any resources of the vtable's type, for `u8` it is trivial, but for `String` it +any resources of the vtable’s type, for `u8` it is trivial, but for `String` it will free the memory. This is necessary for owning trait objects like `Box`, which need to clean-up both the `Box` allocation as well as the internal type when they go out of scope. The `size` and `align` fields store @@ -270,11 +270,11 @@ essentially unused at the moment since the information is embedded in the destructor, but will be used in the future, as trait objects are progressively made more flexible. -Suppose we've got some values that implement `Foo`, then the explicit form of +Suppose we’ve got some values that implement `Foo`, then the explicit form of construction and use of `Foo` trait objects might look a bit like (ignoring the -type mismatches: they're all just pointers anyway): +type mismatches: they’re all just pointers anyway): -```{rust,ignore} +```rust,ignore let a: String = "foo".to_string(); let x: u8 = 1; diff --git a/src/doc/trpl/tuple-structs.md b/src/doc/trpl/tuple-structs.md index 8fba658fba2cd..bdaef70711ae4 100644 --- a/src/doc/trpl/tuple-structs.md +++ b/src/doc/trpl/tuple-structs.md @@ -1,16 +1,20 @@ % Tuple Structs -Rust has another data type that's like a hybrid between a tuple and a struct, -called a *tuple struct*. Tuple structs do have a name, but their fields don't: +Rust has another data type that's like a hybrid between a [tuple][tuple] and a +[struct][struct], called a ‘tuple struct’. Tuple structs have a name, but +their fields don’t: -```{rust} +```rust struct Color(i32, i32, i32); struct Point(i32, i32, i32); ``` +[tuple]: primitive-types.html#tuples +[struct]: structs.html + These two will not be equal, even if they have the same values: -```{rust} +```rust # struct Color(i32, i32, i32); # struct Point(i32, i32, i32); let black = Color(0, 0, 0); @@ -20,7 +24,7 @@ let origin = Point(0, 0, 0); It is almost always better to use a struct than a tuple struct. We would write `Color` and `Point` like this instead: -```{rust} +```rust struct Color { red: i32, blue: i32, @@ -37,12 +41,12 @@ struct Point { Now, we have actual names, rather than positions. Good names are important, and with a struct, we have actual names. -There _is_ one case when a tuple struct is very useful, though, and that's a -tuple struct with only one element. We call this the *newtype* pattern, because +There _is_ one case when a tuple struct is very useful, though, and that’s a +tuple struct with only one element. We call this the ‘newtype’ pattern, because it allows you to create a new type, distinct from that of its contained value and expressing its own semantic meaning: -```{rust} +```rust struct Inches(i32); let length = Inches(10); @@ -52,5 +56,5 @@ println!("length is {} inches", integer_length); ``` As you can see here, you can extract the inner integer type through a -destructuring `let`, as we discussed previously in 'tuples.' In this case, the +destructuring `let`, as we discussed previously in ‘tuples’. In this case, the `let Inches(integer_length)` assigns `10` to `integer_length`. diff --git a/src/doc/trpl/unsafe-code.md b/src/doc/trpl/unsafe.md similarity index 98% rename from src/doc/trpl/unsafe-code.md rename to src/doc/trpl/unsafe.md index ab5e8ed16ad23..7fe9a1fd27e8e 100644 --- a/src/doc/trpl/unsafe-code.md +++ b/src/doc/trpl/unsafe.md @@ -1,4 +1,4 @@ -% Unsafe Code +% Unsafe Rust’s main draw is its powerful static guarantees about behavior. But safety checks are conservative by nature: there are some programs that are actually @@ -76,7 +76,7 @@ behaviors that are certainly bad, but are expressly _not_ unsafe: * Integer overflow Rust cannot prevent all kinds of software problems. Buggy code can and will be -written in Rust. These things arne’t great, but they don’t qualify as `unsafe` +written in Rust. These things aren’t great, but they don’t qualify as `unsafe` specifically. # Unsafe Superpowers diff --git a/src/etc/mklldeps.py b/src/etc/mklldeps.py index e5e8c9f11bd82..fe9feb3538d15 100644 --- a/src/etc/mklldeps.py +++ b/src/etc/mklldeps.py @@ -46,13 +46,8 @@ def run(args): f.write("\n") -version = run([llconfig, '--version']).strip() - # LLVM libs -if version < '3.5': - args = [llconfig, '--libs'] -else: - args = [llconfig, '--libs', '--system-libs'] +args = [llconfig, '--libs', '--system-libs'] args.extend(components) out = run(args) @@ -73,11 +68,6 @@ def run(args): f.write(", kind = \"static\"") f.write(")]\n") -# llvm-config before 3.5 didn't have a system-libs flag -if version < '3.5': - if os == 'win32': - f.write("#[link(name = \"imagehlp\")]") - # LLVM ldflags out = run([llconfig, '--ldflags']) for lib in out.strip().split(' '): diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 3afc34be2cac8..554ca3ea539cb 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -77,7 +77,6 @@ use core::atomic; use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst}; use core::fmt; use core::cmp::Ordering; -use core::default::Default; use core::mem::{min_align_of, size_of}; use core::mem; use core::nonzero::NonZero; diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 009266c3d2c61..7696abd659f02 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -55,7 +55,6 @@ use core::prelude::*; use core::any::Any; use core::cmp::Ordering; -use core::default::Default; use core::fmt; use core::hash::{self, Hash}; use core::mem; diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 3804874a650f6..0f05e5796aa15 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -152,8 +152,7 @@ use core::prelude::*; -use core::default::Default; -use core::iter::{FromIterator, IntoIterator}; +use core::iter::{FromIterator}; use core::mem::{zeroed, replace, swap}; use core::ptr; @@ -250,28 +249,6 @@ impl BinaryHeap { Iter { iter: self.data.iter() } } - /// Creates a consuming iterator, that is, one that moves each value out of - /// the binary heap in arbitrary order. The binary heap cannot be used - /// after calling this. - /// - /// # Examples - /// - /// ``` - /// # #![feature(collections)] - /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); - /// - /// // Print 1, 2, 3, 4 in arbitrary order - /// for x in heap.into_iter() { - /// // x has type i32, not &i32 - /// println!("{}", x); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter { iter: self.data.into_iter() } - } - /// Returns the greatest item in the binary heap, or `None` if it is empty. /// /// # Examples @@ -675,8 +652,25 @@ impl IntoIterator for BinaryHeap { type Item = T; type IntoIter = IntoIter; + /// Creates a consuming iterator, that is, one that moves each value out of + /// the binary heap in arbitrary order. The binary heap cannot be used + /// after calling this. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); + /// + /// // Print 1, 2, 3, 4 in arbitrary order + /// for x in heap.into_iter() { + /// // x has type i32, not &i32 + /// println!("{}", x); + /// } + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + IntoIter { iter: self.data.into_iter() } } } diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index bb90363bc1ddf..d9151298a35e3 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -84,12 +84,11 @@ use core::prelude::*; use core::cmp::Ordering; use core::cmp; -use core::default::Default; use core::fmt; use core::hash; use core::iter::RandomAccessIterator; use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned}; -use core::iter::{self, FromIterator, IntoIterator}; +use core::iter::{self, FromIterator}; use core::ops::Index; use core::slice; use core::{u8, u32, usize}; diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index ef335e31e08cb..291b66939e5ef 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -20,10 +20,9 @@ use self::Entry::*; use core::prelude::*; use core::cmp::Ordering; -use core::default::Default; use core::fmt::Debug; use core::hash::{Hash, Hasher}; -use core::iter::{Map, FromIterator, IntoIterator}; +use core::iter::{Map, FromIterator}; use core::ops::Index; use core::{iter, fmt, mem, usize}; use Bound::{self, Included, Excluded, Unbounded}; @@ -471,8 +470,32 @@ impl IntoIterator for BTreeMap { type Item = (K, V); type IntoIter = IntoIter; + /// Gets an owning iterator over the entries of the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// map.insert(3, "c"); + /// + /// for (key, value) in map.into_iter() { + /// println!("{}: {}", key, value); + /// } + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + let len = self.len(); + let mut lca = VecDeque::new(); + lca.push_back(Traverse::traverse(self.root)); + IntoIter { + inner: AbsIter { + traversals: lca, + size: len, + } + } } } @@ -1263,35 +1286,6 @@ impl BTreeMap { } } - /// Gets an owning iterator over the entries of the map. - /// - /// # Examples - /// - /// ``` - /// use std::collections::BTreeMap; - /// - /// let mut map = BTreeMap::new(); - /// map.insert(1, "a"); - /// map.insert(2, "b"); - /// map.insert(3, "c"); - /// - /// for (key, value) in map.into_iter() { - /// println!("{}: {}", key, value); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - let len = self.len(); - let mut lca = VecDeque::new(); - lca.push_back(Traverse::traverse(self.root)); - IntoIter { - inner: AbsIter { - traversals: lca, - size: len, - } - } - } - /// Gets an iterator over the keys of the map. /// /// # Examples diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 1abd56fd1458d..fc346151e0b4b 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -14,10 +14,9 @@ use core::prelude::*; use core::cmp::Ordering::{self, Less, Greater, Equal}; -use core::default::Default; use core::fmt::Debug; use core::fmt; -use core::iter::{Peekable, Map, FromIterator, IntoIterator}; +use core::iter::{Peekable, Map, FromIterator}; use core::ops::{BitOr, BitAnd, BitXor, Sub}; use borrow::Borrow; @@ -132,27 +131,6 @@ impl BTreeSet { pub fn iter(&self) -> Iter { Iter { iter: self.map.keys() } } - - /// Gets an iterator for moving out the BtreeSet's contents. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::collections::BTreeSet; - /// - /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); - /// - /// let v: Vec = set.into_iter().collect(); - /// assert_eq!(v, [1, 2, 3, 4]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn first((a, _): (A, B)) -> A { a } - let first: fn((T, ())) -> T = first; // coerce to fn pointer - - IntoIter { iter: self.map.into_iter().map(first) } - } } impl BTreeSet { @@ -500,8 +478,24 @@ impl IntoIterator for BTreeSet { type Item = T; type IntoIter = IntoIter; + /// Gets an iterator for moving out the BtreeSet's contents. + /// + /// # Examples + /// + /// ``` + /// # #![feature(core)] + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); + /// + /// let v: Vec = set.into_iter().collect(); + /// assert_eq!(v, [1, 2, 3, 4]); + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + fn first((a, _): (A, B)) -> A { a } + let first: fn((T, ())) -> T = first; // coerce to fn pointer + + IntoIter { iter: self.map.into_iter().map(first) } } } diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index a3a266669b1bb..e6cdb88d3e174 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -16,7 +16,7 @@ use core::prelude::*; use core::marker; use core::fmt; -use core::iter::{FromIterator, IntoIterator}; +use core::iter::{FromIterator}; use core::ops::{Sub, BitOr, BitAnd, BitXor}; // FIXME(contentions): implement union family of methods? (general design may be wrong here) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index d8a0e4daf4398..2b502b2227ef3 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -260,7 +260,6 @@ //! Example usage is: //! //! ``` -//! # #![feature(old_io)] //! # #![allow(unused_must_use)] //! use std::io::Write; //! let mut w = Vec::new(); @@ -288,7 +287,6 @@ //! off, some example usage is: //! //! ``` -//! # #![feature(old_io)] //! use std::fmt; //! use std::io::{self, Write}; //! diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 9a35ac1f6983e..0ea8975bbde1f 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -38,6 +38,7 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(step_by)] #![feature(str_char)] +#![feature(str_words)] #![feature(slice_patterns)] #![feature(debug_builders)] #![feature(utf8_error)] diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 391439bcdf2ff..deb1476c23f09 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -25,10 +25,9 @@ use core::prelude::*; use alloc::boxed::Box; use core::cmp::Ordering; -use core::default::Default; use core::fmt; use core::hash::{Hasher, Hash}; -use core::iter::{self, FromIterator, IntoIterator}; +use core::iter::{self, FromIterator}; use core::mem; use core::ptr; @@ -296,13 +295,6 @@ impl LinkedList { } } - /// Consumes the list into an iterator yielding elements by value. - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter{list: self} - } - /// Returns `true` if the `LinkedList` is empty. /// /// This operation should compute in O(1) time. @@ -852,8 +844,10 @@ impl IntoIterator for LinkedList { type Item = T; type IntoIter = IntoIter; + /// Consumes the list into an iterator yielding elements by value. + #[inline] fn into_iter(self) -> IntoIter { - self.into_iter() + IntoIter{list: self} } } @@ -941,7 +935,7 @@ impl Hash for LinkedList { #[cfg(test)] mod test { use std::clone::Clone; - use std::iter::Iterator; + use std::iter::{Iterator, IntoIterator}; use std::option::Option::{Some, None, self}; use std::__rand::{thread_rng, Rng}; use std::thread; diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index c62bde482b73c..db9f526a0f22e 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -76,7 +76,7 @@ pub use core::str::{Matches, RMatches}; pub use core::str::{MatchIndices, RMatchIndices}; pub use core::str::{from_utf8, Chars, CharIndices, Bytes}; pub use core::str::{from_utf8_unchecked, ParseBoolError}; -pub use rustc_unicode::str::{Words, Graphemes, GraphemeIndices}; +pub use rustc_unicode::str::{SplitWhitespace, Words, Graphemes, GraphemeIndices}; pub use core::str::pattern; /* @@ -1737,27 +1737,44 @@ impl str { UnicodeStr::grapheme_indices(&self[..], is_extended) } - /// An iterator over the non-empty words of `self`. - /// - /// A 'word' is a subsequence separated by any sequence of whitespace. - /// Sequences of whitespace - /// are collapsed, so empty "words" are not included. + /// An iterator over the non-empty substrings of `self` which contain no whitespace, + /// and which are separated by any amount of whitespace. /// /// # Examples /// /// ``` /// # #![feature(str_words)] + /// # #![allow(deprecated)] /// let some_words = " Mary had\ta little \n\t lamb"; /// let v: Vec<&str> = some_words.words().collect(); /// /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); /// ``` + #[deprecated(reason = "words() will be removed. Use split_whitespace() instead", + since = "1.1.0")] #[unstable(feature = "str_words", reason = "the precise algorithm to use is unclear")] + #[allow(deprecated)] pub fn words(&self) -> Words { UnicodeStr::words(&self[..]) } + /// An iterator over the non-empty substrings of `self` which contain no whitespace, + /// and which are separated by any amount of whitespace. + /// + /// # Examples + /// + /// ``` + /// let some_words = " Mary had\ta little \n\t lamb"; + /// let v: Vec<&str> = some_words.split_whitespace().collect(); + /// + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// ``` + #[stable(feature = "split_whitespace", since = "1.1.0")] + pub fn split_whitespace(&self) -> SplitWhitespace { + UnicodeStr::split_whitespace(&self[..]) + } + /// Returns a string's displayed width in columns. /// /// Control characters have zero width. diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 07b99402cd2c3..a37a26ef22ac3 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -14,10 +14,9 @@ use core::prelude::*; -use core::default::Default; use core::fmt; use core::hash; -use core::iter::{IntoIterator, FromIterator}; +use core::iter::FromIterator; use core::mem; use core::ops::{self, Deref, Add, Index}; use core::ptr; @@ -1065,4 +1064,10 @@ impl fmt::Write for String { self.push_str(s); Ok(()) } + + #[inline] + fn write_char(&mut self, c: char) -> fmt::Result { + self.push(c); + Ok(()) + } } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 813f88c47286d..526150915a705 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -53,11 +53,10 @@ use alloc::boxed::Box; use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; use core::cmp::max; use core::cmp::Ordering; -use core::default::Default; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::assume; -use core::iter::{repeat, FromIterator, IntoIterator}; +use core::iter::{repeat, FromIterator}; use core::marker::PhantomData; use core::mem; use core::ops::{Index, IndexMut, Deref, Add}; @@ -450,37 +449,6 @@ impl Vec { &mut self[..] } - /// Creates a consuming iterator, that is, one that moves each value out of - /// the vector (from start to end). The vector cannot be used after calling - /// this. - /// - /// # Examples - /// - /// ``` - /// let v = vec!["a".to_string(), "b".to_string()]; - /// for s in v.into_iter() { - /// // s has type String, not &String - /// println!("{}", s); - /// } - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - unsafe { - let ptr = *self.ptr; - assume(!ptr.is_null()); - let cap = self.cap; - let begin = ptr as *const T; - let end = if mem::size_of::() == 0 { - (ptr as usize + self.len()) as *const T - } else { - ptr.offset(self.len() as isize) as *const T - }; - mem::forget(self); - IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end } - } - } - /// Sets the length of a vector. /// /// This will explicitly set the size of the vector, without actually @@ -1512,8 +1480,34 @@ impl IntoIterator for Vec { type Item = T; type IntoIter = IntoIter; + /// Creates a consuming iterator, that is, one that moves each value out of + /// the vector (from start to end). The vector cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["a".to_string(), "b".to_string()]; + /// for s in v.into_iter() { + /// // s has type String, not &String + /// println!("{}", s); + /// } + /// ``` + #[inline] fn into_iter(self) -> IntoIter { - self.into_iter() + unsafe { + let ptr = *self.ptr; + assume(!ptr.is_null()); + let cap = self.cap; + let begin = ptr as *const T; + let end = if mem::size_of::() == 0 { + (ptr as usize + self.len()) as *const T + } else { + ptr.offset(self.len() as isize) as *const T + }; + mem::forget(self); + IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end } + } } } diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 858838a3a4ba5..bbe7830b4238c 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -21,9 +21,8 @@ use core::prelude::*; use core::cmp::Ordering; -use core::default::Default; use core::fmt; -use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; +use core::iter::{self, repeat, FromIterator, RandomAccessIterator}; use core::mem; use core::ops::{Index, IndexMut}; use core::ptr::{self, Unique}; @@ -557,14 +556,6 @@ impl VecDeque { } } - /// Consumes the list into a front-to-back iterator yielding elements by value. - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter { - inner: self, - } - } - /// Returns a pair of slices which contain, in order, the contents of the /// `VecDeque`. #[inline] @@ -1728,8 +1719,12 @@ impl IntoIterator for VecDeque { type Item = T; type IntoIter = IntoIter; + /// Consumes the list into a front-to-back iterator yielding elements by + /// value. fn into_iter(self) -> IntoIter { - self.into_iter() + IntoIter { + inner: self, + } } } diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 07d783ef46a7b..d473504d54454 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -18,10 +18,9 @@ use self::Entry::*; use core::prelude::*; use core::cmp::{max, Ordering}; -use core::default::Default; use core::fmt; use core::hash::{Hash, Hasher}; -use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator}; +use core::iter::{Enumerate, FilterMap, Map, FromIterator}; use core::iter; use core::mem::{replace, swap}; use core::ops::{Index, IndexMut}; @@ -301,35 +300,6 @@ impl VecMap { } } - /// Returns an iterator visiting all key-value pairs in ascending order of - /// the keys, consuming the original `VecMap`. - /// The iterator's element type is `(usize, &'r V)`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(collections)] - /// use std::collections::VecMap; - /// - /// let mut map = VecMap::new(); - /// map.insert(1, "a"); - /// map.insert(3, "c"); - /// map.insert(2, "b"); - /// - /// let vec: Vec<(usize, &str)> = map.into_iter().collect(); - /// - /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn filter((i, v): (usize, Option)) -> Option<(usize, A)> { - v.map(|v| (i, v)) - } - let filter: fn((usize, Option)) -> Option<(usize, V)> = filter; // coerce to fn ptr - - IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) } - } - /// Moves all elements from `other` into the map while overwriting existing keys. /// /// # Examples @@ -800,8 +770,32 @@ impl IntoIterator for VecMap { type Item = (usize, T); type IntoIter = IntoIter; + /// Returns an iterator visiting all key-value pairs in ascending order of + /// the keys, consuming the original `VecMap`. + /// The iterator's element type is `(usize, &'r V)`. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// map.insert(3, "c"); + /// map.insert(2, "b"); + /// + /// let vec: Vec<(usize, &str)> = map.into_iter().collect(); + /// + /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + fn filter((i, v): (usize, Option)) -> Option<(usize, A)> { + v.map(|v| (i, v)) + } + let filter: fn((usize, Option)) -> Option<(usize, T)> = filter; // coerce to fn ptr + + IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) } } } diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 549ff17e46902..5c109dc8104f2 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -14,7 +14,6 @@ #![feature(hash)] #![feature(rand)] #![feature(rustc_private)] -#![feature(str_words)] #![feature(test)] #![feature(unboxed_closures)] #![feature(unicode)] diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index e23a8a34b09ce..170f49ab15be5 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -939,9 +939,9 @@ fn test_rsplitn() { } #[test] -fn test_words() { +fn test_split_whitespace() { let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; - let words: Vec<&str> = data.words().collect(); + let words: Vec<&str> = data.split_whitespace().collect(); assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 5cff0186f2506..0178b321e88c3 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -78,6 +78,23 @@ pub trait Write { #[stable(feature = "rust1", since = "1.0.0")] fn write_str(&mut self, s: &str) -> Result; + /// Writes a `char` into this writer, returning whether the write succeeded. + /// + /// A single `char` may be encoded as more than one byte. + /// This method can only succeed if the entire byte sequence was successfully + /// written, and this method will not return until all data has been + /// written or an error occurs. + /// + /// # Errors + /// + /// This function will return an instance of `FormatError` on error. + #[stable(feature = "fmt_write_char", since = "1.1.0")] + fn write_char(&mut self, c: char) -> Result { + let mut utf_8 = [0u8; 4]; + let bytes_written = c.encode_utf8(&mut utf_8).unwrap_or(0); + self.write_str(unsafe { mem::transmute(&utf_8[..bytes_written]) }) + } + /// Glue for usage of the `write!` macro with implementers of this trait. /// /// This method should generally not be invoked manually, but rather through diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 553e0c0dfe6e4..e848a44e01ce0 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -62,7 +62,6 @@ use prelude::*; -use default::Default; use mem; pub use self::sip::SipHasher; diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 65f790d5d432e..be419e2cdadb0 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -13,7 +13,6 @@ #![allow(deprecated)] // until the next snapshot for inherent wrapping ops use prelude::*; -use default::Default; use super::Hasher; /// An implementation of SipHash 2-4. diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 4c784a579da6b..d1bc24bd9baa5 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -551,25 +551,6 @@ impl Option { IterMut { inner: Item { opt: self.as_mut() } } } - /// Returns a consuming iterator over the possibly contained value. - /// - /// # Examples - /// - /// ``` - /// let x = Some("string"); - /// let v: Vec<&str> = x.into_iter().collect(); - /// assert_eq!(v, ["string"]); - /// - /// let x = None; - /// let v: Vec<&str> = x.into_iter().collect(); - /// assert!(v.is_empty()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter { inner: Item { opt: self } } - } - ///////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -770,6 +751,30 @@ impl Default for Option { fn default() -> Option { None } } +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Option { + type Item = T; + type IntoIter = IntoIter; + + /// Returns a consuming iterator over the possibly contained value. + /// + /// # Examples + /// + /// ``` + /// let x = Some("string"); + /// let v: Vec<&str> = x.into_iter().collect(); + /// assert_eq!(v, ["string"]); + /// + /// let x = None; + /// let v: Vec<&str> = x.into_iter().collect(); + /// assert!(v.is_empty()); + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + IntoIter { inner: Item { opt: self } } + } +} + ///////////////////////////////////////////////////////////////////////////// // The Option Iterators ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 12f01f2651c73..a4d529ad47d09 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -37,6 +37,8 @@ pub use char::CharExt; pub use clone::Clone; pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; pub use convert::{AsRef, AsMut, Into, From}; +pub use default::Default; +pub use iter::IntoIterator; pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator}; pub use option::Option::{self, Some, None}; pub use result::Result::{self, Ok, Err}; diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 96f575cc548fe..e909946ece402 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -545,25 +545,6 @@ impl Result { IterMut { inner: self.as_mut().ok() } } - /// Returns a consuming iterator over the possibly contained value. - /// - /// # Examples - /// - /// ``` - /// let x: Result = Ok(5); - /// let v: Vec = x.into_iter().collect(); - /// assert_eq!(v, [5]); - /// - /// let x: Result = Err("nothing!"); - /// let v: Vec = x.into_iter().collect(); - /// assert_eq!(v, []); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter { inner: self.ok() } - } - //////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -781,6 +762,34 @@ impl Result { } } +///////////////////////////////////////////////////////////////////////////// +// Trait implementations +///////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Result { + type Item = T; + type IntoIter = IntoIter; + + /// Returns a consuming iterator over the possibly contained value. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(5); + /// let v: Vec = x.into_iter().collect(); + /// assert_eq!(v, [5]); + /// + /// let x: Result = Err("nothing!"); + /// let v: Vec = x.into_iter().collect(); + /// assert_eq!(v, []); + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + IntoIter { inner: self.ok() } + } +} + ///////////////////////////////////////////////////////////////////////////// // The Result Iterators ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 197199e743f57..5782c57834eed 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -91,7 +91,6 @@ #![deny(missing_docs)] #![feature(staged_api)] -#![feature(str_words)] #![feature(str_char)] #![cfg_attr(test, feature(rustc_private))] @@ -771,7 +770,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { // Normalize desc to contain words separated by one space character let mut desc_normalized_whitespace = String::new(); - for word in desc.words() { + for word in desc.split_whitespace() { desc_normalized_whitespace.push_str(word); desc_normalized_whitespace.push(' '); } diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 24a4a45722471..4fbcdaa378e25 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -3536,6 +3536,30 @@ pub mod consts { pub const IPV6_DROP_MEMBERSHIP: c_int = 21; pub const TCP_NODELAY: c_int = 1; + pub const TCP_MAXSEG: c_int = 2; + pub const TCP_CORK: c_int = 3; + pub const TCP_KEEPIDLE: c_int = 4; + pub const TCP_KEEPINTVL: c_int = 5; + pub const TCP_KEEPCNT: c_int = 6; + pub const TCP_SYNCNT: c_int = 7; + pub const TCP_LINGER2: c_int = 8; + pub const TCP_DEFER_ACCEPT: c_int = 9; + pub const TCP_WINDOW_CLAMP: c_int = 10; + pub const TCP_INFO: c_int = 11; + pub const TCP_QUICKACK: c_int = 12; + pub const TCP_CONGESTION: c_int = 13; + pub const TCP_MD5SIG: c_int = 14; + pub const TCP_COOKIE_TRANSACTIONS: c_int = 15; + pub const TCP_THIN_LINEAR_TIMEOUTS: c_int = 16; + pub const TCP_THIN_DUPACK: c_int = 17; + pub const TCP_USER_TIMEOUT: c_int = 18; + pub const TCP_REPAIR: c_int = 19; + pub const TCP_REPAIR_QUEUE: c_int = 20; + pub const TCP_QUEUE_SEQ: c_int = 21; + pub const TCP_REPAIR_OPTIONS: c_int = 22; + pub const TCP_FASTOPEN: c_int = 23; + pub const TCP_TIMESTAMP: c_int = 24; + pub const SOL_SOCKET: c_int = 1; pub const SO_DEBUG: c_int = 1; diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index 287a23cf1d1b6..ea084b2816dd1 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -14,7 +14,6 @@ use core::prelude::*; use {Rng, SeedableRng}; -use core::default::Default; /// How many bytes of entropy the underling RNG is allowed to generate /// before it is reseeded. @@ -126,7 +125,6 @@ mod test { use core::iter::{order, repeat}; use super::{ReseedingRng, ReseedWithDefault}; - use std::default::Default; use {SeedableRng, Rng}; struct Counter { diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index ba226c88e5623..33ecc0ce20507 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -208,7 +208,7 @@ fn main() { unsafe { f(); } } -See also http://doc.rust-lang.org/book/unsafe-code.html +See also http://doc.rust-lang.org/book/unsafe.html "##, E0152: r##" diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index b65bd965976d1..9093b3b9f5c91 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -38,7 +38,6 @@ #![feature(staged_api)] #![feature(std_misc)] #![feature(path_ext)] -#![feature(str_words)] #![feature(str_char)] #![feature(into_cow)] #![feature(slice_patterns)] diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 398e4cd33b943..bbb2452ca29ee 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -692,11 +692,16 @@ pub fn note_crate_name(diag: &SpanHandler, name: &str) { impl ArchiveMetadata { fn new(ar: ArchiveRO) -> Option { - let data = match ar.read(METADATA_FILENAME) { - Some(data) => data as *const [u8], - None => { - debug!("didn't find '{}' in the archive", METADATA_FILENAME); - return None; + let data = { + let section = ar.iter().find(|sect| { + sect.name() == Some(METADATA_FILENAME) + }); + match section { + Some(s) => s.data() as *const [u8], + None => { + debug!("didn't find '{}' in the archive", METADATA_FILENAME); + return None; + } } }; diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index a9da92a768fe6..6f40e17855a78 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -24,6 +24,7 @@ use middle::region; use middle::subst; use middle::ty; use std::fmt; +use std::mem::replace; use syntax::ast; use syntax::codemap::Span; use syntax::parse::token::special_idents; @@ -70,6 +71,9 @@ struct LifetimeContext<'a> { // I'm sorry. trait_ref_hack: bool, + + // List of labels in the function/method currently under analysis. + labels_in_fn: Vec<(ast::Ident, Span)>, } enum ScopeChain<'a> { @@ -97,6 +101,7 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio scope: &ROOT_SCOPE, def_map: def_map, trait_ref_hack: false, + labels_in_fn: vec![], }, krate); sess.abort_if_errors(); named_region_map @@ -104,6 +109,10 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { fn visit_item(&mut self, item: &ast::Item) { + // Items save/restore the set of labels. This way innner items + // can freely reuse names, be they loop labels or lifetimes. + let saved = replace(&mut self.labels_in_fn, vec![]); + // Items always introduce a new root scope self.with(RootScope, |_, this| { match item.node { @@ -137,6 +146,9 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } } }); + + // Done traversing the item; restore saved set of labels. + replace(&mut self.labels_in_fn, saved); } fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, @@ -144,16 +156,16 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { match fk { visit::FkItemFn(_, generics, _, _, _) => { self.visit_early_late(subst::FnSpace, generics, |this| { - visit::walk_fn(this, fk, fd, b, s) + this.walk_fn(fk, fd, b, s) }) } visit::FkMethod(_, sig, _) => { self.visit_early_late(subst::FnSpace, &sig.generics, |this| { - visit::walk_fn(this, fk, fd, b, s) + this.walk_fn(fk, fd, b, s) }) } visit::FkFnBlock(..) => { - visit::walk_fn(self, fk, fd, b, s) + self.walk_fn(fk, fd, b, s) } } } @@ -190,6 +202,10 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { + // We reset the labels on every trait item, so that different + // methods in an impl can reuse label names. + let saved = replace(&mut self.labels_in_fn, vec![]); + if let ast::MethodTraitItem(ref sig, None) = trait_item.node { self.visit_early_late( subst::FnSpace, &sig.generics, @@ -197,6 +213,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } else { visit::walk_trait_item(self, trait_item); } + + replace(&mut self.labels_in_fn, saved); } fn visit_block(&mut self, b: &ast::Block) { @@ -286,7 +304,170 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } } +#[derive(Copy, Clone, PartialEq)] +enum ShadowKind { Label, Lifetime } +struct Original { kind: ShadowKind, span: Span } +struct Shadower { kind: ShadowKind, span: Span } + +fn original_label(span: Span) -> Original { + Original { kind: ShadowKind::Label, span: span } +} +fn shadower_label(span: Span) -> Shadower { + Shadower { kind: ShadowKind::Label, span: span } +} +fn original_lifetime(l: &ast::Lifetime) -> Original { + Original { kind: ShadowKind::Lifetime, span: l.span } +} +fn shadower_lifetime(l: &ast::Lifetime) -> Shadower { + Shadower { kind: ShadowKind::Lifetime, span: l.span } +} + +impl ShadowKind { + fn desc(&self) -> &'static str { + match *self { + ShadowKind::Label => "label", + ShadowKind::Lifetime => "lifetime", + } + } +} + +fn signal_shadowing_problem( + sess: &Session, name: ast::Name, orig: Original, shadower: Shadower) { + if let (ShadowKind::Lifetime, ShadowKind::Lifetime) = (orig.kind, shadower.kind) { + // lifetime/lifetime shadowing is an error + sess.span_err(shadower.span, + &format!("{} name `{}` shadows a \ + {} name that is already in scope", + shadower.kind.desc(), name, orig.kind.desc())); + } else { + // shadowing involving a label is only a warning, due to issues with + // labels and lifetimes not being macro-hygienic. + sess.span_warn(shadower.span, + &format!("{} name `{}` shadows a \ + {} name that is already in scope", + shadower.kind.desc(), name, orig.kind.desc())); + } + sess.span_note(orig.span, + &format!("shadowed {} `{}` declared here", + orig.kind.desc(), name)); +} + +// Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning +// if one of the label shadows a lifetime or another label. +fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v ast::Block) { + + struct GatherLabels<'a> { + sess: &'a Session, + scope: Scope<'a>, + labels_in_fn: &'a mut Vec<(ast::Ident, Span)>, + } + + let mut gather = GatherLabels { + sess: ctxt.sess, + scope: ctxt.scope, + labels_in_fn: &mut ctxt.labels_in_fn, + }; + gather.visit_block(b); + return; + + impl<'v, 'a> Visitor<'v> for GatherLabels<'a> { + fn visit_expr(&mut self, ex: &'v ast::Expr) { + if let Some(label) = expression_label(ex) { + for &(prior, prior_span) in &self.labels_in_fn[..] { + // FIXME (#24278): non-hygienic comparision + if label.name == prior.name { + signal_shadowing_problem(self.sess, + label.name, + original_label(prior_span), + shadower_label(ex.span)); + } + } + + check_if_label_shadows_lifetime(self.sess, + self.scope, + label, + ex.span); + + self.labels_in_fn.push((label, ex.span)); + } + visit::walk_expr(self, ex) + } + + fn visit_item(&mut self, _: &ast::Item) { + // do not recurse into items defined in the block + } + } + + fn expression_label(ex: &ast::Expr) -> Option { + match ex.node { + ast::ExprWhile(_, _, Some(label)) | + ast::ExprWhileLet(_, _, _, Some(label)) | + ast::ExprForLoop(_, _, _, Some(label)) | + ast::ExprLoop(_, Some(label)) => Some(label), + _ => None, + } + } + + fn check_if_label_shadows_lifetime<'a>(sess: &'a Session, + mut scope: Scope<'a>, + label: ast::Ident, + label_span: Span) { + loop { + match *scope { + BlockScope(_, s) => { scope = s; } + RootScope => { return; } + + EarlyScope(_, lifetimes, s) | + LateScope(lifetimes, s) => { + for lifetime_def in lifetimes { + // FIXME (#24278): non-hygienic comparision + if label.name == lifetime_def.lifetime.name { + signal_shadowing_problem( + sess, + label.name, + original_lifetime(&lifetime_def.lifetime), + shadower_label(label_span)); + return; + } + } + scope = s; + } + } + } + } +} + impl<'a> LifetimeContext<'a> { + // This is just like visit::walk_fn, except that it extracts the + // labels of the function body and swaps them in before visiting + // the function body itself. + fn walk_fn<'b>(&mut self, + fk: visit::FnKind, + fd: &ast::FnDecl, + fb: &'b ast::Block, + _span: Span) { + match fk { + visit::FkItemFn(_, generics, _, _, _) => { + visit::walk_fn_decl(self, fd); + self.visit_generics(generics); + } + visit::FkMethod(_, sig, _) => { + visit::walk_fn_decl(self, fd); + self.visit_generics(&sig.generics); + self.visit_explicit_self(&sig.explicit_self); + } + visit::FkFnBlock(..) => { + visit::walk_fn_decl(self, fd); + } + } + + // After inpsecting the decl, add all labels from the body to + // `self.labels_in_fn`. + extract_labels(self, fb); + + self.visit_block(fb); + } + fn with(&mut self, wrap_scope: ScopeChain, f: F) where F: FnOnce(Scope, &mut LifetimeContext), { @@ -297,6 +478,7 @@ impl<'a> LifetimeContext<'a> { scope: &wrap_scope, def_map: self.def_map, trait_ref_hack: self.trait_ref_hack, + labels_in_fn: self.labels_in_fn.clone(), }; debug!("entering scope {:?}", this.scope); f(self.scope, &mut this); @@ -494,6 +676,17 @@ impl<'a> LifetimeContext<'a> { mut old_scope: Scope, lifetime: &ast::Lifetime) { + for &(label, label_span) in &self.labels_in_fn { + // FIXME (#24278): non-hygienic comparision + if lifetime.name == label.name { + signal_shadowing_problem(self.sess, + lifetime.name, + original_label(label_span), + shadower_lifetime(&lifetime)); + return; + } + } + loop { match *old_scope { BlockScope(_, s) => { @@ -507,15 +700,11 @@ impl<'a> LifetimeContext<'a> { EarlyScope(_, lifetimes, s) | LateScope(lifetimes, s) => { if let Some((_, lifetime_def)) = search_lifetimes(lifetimes, lifetime) { - self.sess.span_err( - lifetime.span, - &format!("lifetime name `{}` shadows another \ - lifetime name that is already in scope", - token::get_name(lifetime.name))); - self.sess.span_note( - lifetime_def.span, - &format!("shadowed lifetime `{}` declared here", - token::get_name(lifetime.name))); + signal_shadowing_problem( + self.sess, + lifetime.name, + original_lifetime(&lifetime_def), + shadower_lifetime(&lifetime)); return; } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index f7ff8b9e6061a..f4ea069447fdf 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -418,7 +418,7 @@ macro_rules! options { -> bool { match v { Some(s) => { - for s in s.words() { + for s in s.split_whitespace() { slot.push(s.to_string()); } true @@ -431,7 +431,7 @@ macro_rules! options { -> bool { match v { Some(s) => { - let v = s.words().map(|s| s.to_string()).collect(); + let v = s.split_whitespace().map(|s| s.to_string()).collect(); *slot = Some(v); true }, diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index 9f5751c421ece..37d784692fd0e 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -11,13 +11,14 @@ //! A helper class for dealing with static archives use std::env; -use std::fs; +use std::fs::{self, File}; use std::io::prelude::*; use std::io; use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; use std::str; use syntax::diagnostic::Handler as ErrorHandler; +use rustc_llvm::archive_ro::ArchiveRO; use tempdir::TempDir; @@ -282,17 +283,14 @@ impl<'a> ArchiveBuilder<'a> { mut skip: F) -> io::Result<()> where F: FnMut(&str) -> bool, { - let loc = TempDir::new("rsar").unwrap(); - - // First, extract the contents of the archive to a temporary directory. - // We don't unpack directly into `self.work_dir` due to the possibility - // of filename collisions. - let archive = env::current_dir().unwrap().join(archive); - run_ar(self.archive.handler, &self.archive.maybe_ar_prog, - "x", Some(loc.path()), &[&archive]); + let archive = match ArchiveRO::open(archive) { + Some(ar) => ar, + None => return Err(io::Error::new(io::ErrorKind::Other, + "failed to open archive")), + }; // Next, we must rename all of the inputs to "guaranteed unique names". - // We move each file into `self.work_dir` under its new unique name. + // We write each file into `self.work_dir` under its new unique name. // The reason for this renaming is that archives are keyed off the name // of the files, so if two files have the same name they will override // one another in the archive (bad). @@ -300,27 +298,46 @@ impl<'a> ArchiveBuilder<'a> { // We skip any files explicitly desired for skipping, and we also skip // all SYMDEF files as these are just magical placeholders which get // re-created when we make a new archive anyway. - let files = try!(fs::read_dir(loc.path())); - for file in files { - let file = try!(file).path(); - let filename = file.file_name().unwrap().to_str().unwrap(); - if skip(filename) { continue } + for file in archive.iter() { + let filename = match file.name() { + Some(s) => s, + None => continue, + }; if filename.contains(".SYMDEF") { continue } + if skip(filename) { continue } - let filename = format!("r-{}-{}", name, filename); - // LLDB (as mentioned in back::link) crashes on filenames of exactly - // 16 bytes in length. If we're including an object file with - // exactly 16-bytes of characters, give it some prefix so that it's - // not 16 bytes. - let filename = if filename.len() == 16 { - format!("lldb-fix-{}", filename) - } else { - filename - }; - let new_filename = self.work_dir.path().join(&filename[..]); - try!(fs::rename(&file, &new_filename)); - self.members.push(PathBuf::from(filename)); + // An archive can contain files of the same name multiple times, so + // we need to be sure to not have them overwrite one another when we + // extract them. Consequently we need to find a truly unique file + // name for us! + let mut new_filename = String::new(); + for n in 0.. { + let n = if n == 0 {String::new()} else {format!("-{}", n)}; + new_filename = format!("r{}-{}-{}", n, name, filename); + + // LLDB (as mentioned in back::link) crashes on filenames of + // exactly + // 16 bytes in length. If we're including an object file with + // exactly 16-bytes of characters, give it some prefix so + // that it's not 16 bytes. + new_filename = if new_filename.len() == 16 { + format!("lldb-fix-{}", new_filename) + } else { + new_filename + }; + + let present = self.members.iter().filter_map(|p| { + p.file_name().and_then(|f| f.to_str()) + }).any(|s| s == new_filename); + if !present { + break + } + } + let dst = self.work_dir.path().join(&new_filename); + try!(try!(File::create(&dst)).write_all(file.data())); + self.members.push(PathBuf::from(new_filename)); } + Ok(()) } } diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 3c54d6631f893..22dea4757ed66 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -46,6 +46,7 @@ extern crate syntax; extern crate libc; extern crate serialize; +extern crate rustc_llvm; #[macro_use] extern crate log; pub mod abi; diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index 647f4bc6a40fd..c8f3e204c4e10 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -10,15 +10,23 @@ //! A wrapper around LLVM's archive (.a) code -use libc; use ArchiveRef; use std::ffi::CString; -use std::slice; use std::path::Path; +use std::slice; +use std::str; -pub struct ArchiveRO { - ptr: ArchiveRef, +pub struct ArchiveRO { ptr: ArchiveRef } + +pub struct Iter<'a> { + archive: &'a ArchiveRO, + ptr: ::ArchiveIteratorRef, +} + +pub struct Child<'a> { + name: Option<&'a str>, + data: &'a [u8], } impl ArchiveRO { @@ -52,18 +60,9 @@ impl ArchiveRO { } } - /// Reads a file in the archive - pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> { + pub fn iter(&self) -> Iter { unsafe { - let mut size = 0 as libc::size_t; - let file = CString::new(file).unwrap(); - let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(), - &mut size); - if ptr.is_null() { - None - } else { - Some(slice::from_raw_parts(ptr as *const u8, size as usize)) - } + Iter { ptr: ::LLVMRustArchiveIteratorNew(self.ptr), archive: self } } } } @@ -75,3 +74,47 @@ impl Drop for ArchiveRO { } } } + +impl<'a> Iterator for Iter<'a> { + type Item = Child<'a>; + + fn next(&mut self) -> Option> { + unsafe { + let ptr = ::LLVMRustArchiveIteratorCurrent(self.ptr); + if ptr.is_null() { + return None + } + let mut name_len = 0; + let name_ptr = ::LLVMRustArchiveChildName(ptr, &mut name_len); + let mut data_len = 0; + let data_ptr = ::LLVMRustArchiveChildData(ptr, &mut data_len); + let child = Child { + name: if name_ptr.is_null() { + None + } else { + let name = slice::from_raw_parts(name_ptr as *const u8, + name_len as usize); + str::from_utf8(name).ok().map(|s| s.trim()) + }, + data: slice::from_raw_parts(data_ptr as *const u8, + data_len as usize), + }; + ::LLVMRustArchiveIteratorNext(self.ptr); + Some(child) + } + } +} + +#[unsafe_destructor] +impl<'a> Drop for Iter<'a> { + fn drop(&mut self) { + unsafe { + ::LLVMRustArchiveIteratorFree(self.ptr); + } + } +} + +impl<'a> Child<'a> { + pub fn name(&self) -> Option<&'a str> { self.name } + pub fn data(&self) -> &'a [u8] { self.data } +} diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 7030ee5697954..80e01154655e7 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -30,6 +30,7 @@ #![feature(libc)] #![feature(link_args)] #![feature(staged_api)] +#![feature(unsafe_destructor)] extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; @@ -488,9 +489,12 @@ pub type PassRef = *mut Pass_opaque; #[allow(missing_copy_implementations)] pub enum TargetMachine_opaque {} pub type TargetMachineRef = *mut TargetMachine_opaque; -#[allow(missing_copy_implementations)] pub enum Archive_opaque {} pub type ArchiveRef = *mut Archive_opaque; +pub enum ArchiveIterator_opaque {} +pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque; +pub enum ArchiveChild_opaque {} +pub type ArchiveChildRef = *mut ArchiveChild_opaque; #[allow(missing_copy_implementations)] pub enum Twine_opaque {} pub type TwineRef = *mut Twine_opaque; @@ -2051,13 +2055,17 @@ extern { pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef); pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef; - pub fn LLVMRustArchiveReadSection(AR: ArchiveRef, name: *const c_char, - out_len: *mut size_t) -> *const c_char; + pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef; + pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef); + pub fn LLVMRustArchiveIteratorCurrent(AIR: ArchiveIteratorRef) -> ArchiveChildRef; + pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef, + size: *mut size_t) -> *const c_char; + pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef, + size: *mut size_t) -> *const c_char; + pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef); pub fn LLVMRustDestroyArchive(AR: ArchiveRef); pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef); - pub fn LLVMVersionMajor() -> c_int; - pub fn LLVMVersionMinor() -> c_int; pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, data: *mut *const c_char) -> c_int; diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index e8752ab14b344..6457140bcc0f9 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -60,13 +60,13 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, let file = &file[3..file.len() - 5]; // chop off lib/.rlib debug!("reading {}", file); for i in 0.. { - let bc_encoded = time(sess.time_passes(), - &format!("check for {}.{}.bytecode.deflate", name, i), - (), - |_| { - archive.read(&format!("{}.{}.bytecode.deflate", - file, i)) - }); + let filename = format!("{}.{}.bytecode.deflate", file, i); + let msg = format!("check for {}", filename); + let bc_encoded = time(sess.time_passes(), &msg, (), |_| { + archive.iter().find(|section| { + section.name() == Some(&filename[..]) + }) + }); let bc_encoded = match bc_encoded { Some(data) => data, None => { @@ -76,9 +76,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, path.display())); } // No more bitcode files to read. - break; - }, + break + } }; + let bc_encoded = bc_encoded.data(); let bc_decoded = if is_versioned_bytecode_format(bc_encoded) { time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| { diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index de21d62651499..488a4a8082f9d 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -348,7 +348,7 @@ unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>, match cgcx.lto_ctxt { Some((sess, _)) => { - sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info { + sess.codemap().with_expn_info(ExpnId::from_u32(cookie), |info| match info { Some(ei) => sess.span_err(ei.call_site, msg), None => sess.err(msg), }); diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index d6c85e8b17345..27128827e2676 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -138,7 +138,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx().llcx(), key.as_ptr() as *const c_char, key.len() as c_uint); - let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.to_llvm_cookie()); + let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.into_u32() as i32); llvm::LLVMSetMetadata(r, kind, llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1)); diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index e54962dc08552..b8c45d4751ef8 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -878,16 +878,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option $ret:expr) => ( - if unsafe { llvm::LLVMVersionMinor() >= 4 } { - // The `if key == $name` is already in ifn! - ifn!($name, fn($($arg),*) -> $ret); - } else if *key == $name { - let f = declare::declare_cfn(ccx, stringify!($cname), - Type::func(&[$($arg),*], &$ret), - ty::mk_nil(ccx.tcx())); - ccx.intrinsics().borrow_mut().insert($name, f.clone()); - return Some(f); - } + ifn!($name, fn($($arg),*) -> $ret); ) } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 159b101e85e5f..7c769eca74aab 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -2653,26 +2653,8 @@ fn set_members_of_composite_type(cx: &CrateContext, let mut composite_types_completed = debug_context(cx).composite_types_completed.borrow_mut(); if composite_types_completed.contains(&composite_type_metadata) { - let (llvm_version_major, llvm_version_minor) = unsafe { - (llvm::LLVMVersionMajor(), llvm::LLVMVersionMinor()) - }; - - let actual_llvm_version = llvm_version_major * 1000000 + llvm_version_minor * 1000; - let min_supported_llvm_version = 3 * 1000000 + 4 * 1000; - - if actual_llvm_version < min_supported_llvm_version { - cx.sess().warn(&format!("This version of rustc was built with LLVM \ - {}.{}. Rustc just ran into a known \ - debuginfo corruption problem thatoften \ - occurs with LLVM versions below 3.4. \ - Please use a rustc built with anewer \ - version of LLVM.", - llvm_version_major, - llvm_version_minor)); - } else { - cx.sess().bug("debuginfo::set_members_of_composite_type() - \ - Already completed forward declaration re-encountered."); - } + cx.sess().bug("debuginfo::set_members_of_composite_type() - \ + Already completed forward declaration re-encountered."); } else { composite_types_completed.insert(composite_type_metadata); } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 1e67212871a1e..6bfa80f9c40b3 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -746,11 +746,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let src = to_arg_ty(bcx, llargs[2], tp_ty); let res = AtomicCmpXchg(bcx, ptr, cmp, src, order, strongest_failure_ordering); - if unsafe { llvm::LLVMVersionMinor() >= 5 } { - ExtractValue(bcx, res, 0) - } else { - res - } + ExtractValue(bcx, res, 0) } "load" => { diff --git a/src/librustc_unicode/lib.rs b/src/librustc_unicode/lib.rs index 5c4e643c2a1c5..edfa8db311f35 100644 --- a/src/librustc_unicode/lib.rs +++ b/src/librustc_unicode/lib.rs @@ -45,7 +45,7 @@ mod u_str; pub mod char; pub mod str { - pub use u_str::{UnicodeStr, Words, Graphemes, GraphemeIndices}; + pub use u_str::{UnicodeStr, SplitWhitespace, Words, Graphemes, GraphemeIndices}; pub use u_str::{utf8_char_width, is_utf16, Utf16Items, Utf16Item}; pub use u_str::{utf16_items, Utf16Encoder}; } diff --git a/src/librustc_unicode/u_str.rs b/src/librustc_unicode/u_str.rs index c63c586b6a901..898844e3bf12b 100644 --- a/src/librustc_unicode/u_str.rs +++ b/src/librustc_unicode/u_str.rs @@ -25,9 +25,16 @@ use core::str::Split; use tables::grapheme::GraphemeCat; -/// An iterator over the words of a string, separated by a sequence of whitespace -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Words<'a> { +#[deprecated(reason = "struct Words is being replaced by struct SplitWhitespace", + since = "1.1.0")] +#[unstable(feature = "str_words", + reason = "words() will be replaced by split_whitespace() in 1.1.0")] +pub type Words<'a> = SplitWhitespace<'a>; + +/// An iterator over the non-whitespace substrings of a string, +/// separated by any amount of whitespace. +#[stable(feature = "split_whitespace", since = "1.1.0")] +pub struct SplitWhitespace<'a> { inner: Filter bool>, fn(&&str) -> bool>, } @@ -36,7 +43,9 @@ pub struct Words<'a> { pub trait UnicodeStr { fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>; fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>; + #[allow(deprecated)] fn words<'a>(&'a self) -> Words<'a>; + fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>; fn is_whitespace(&self) -> bool; fn is_alphanumeric(&self) -> bool; fn width(&self, is_cjk: bool) -> usize; @@ -56,15 +65,21 @@ impl UnicodeStr for str { GraphemeIndices { start_offset: self.as_ptr() as usize, iter: self.graphemes(is_extended) } } + #[allow(deprecated)] #[inline] fn words(&self) -> Words { + self.split_whitespace() + } + + #[inline] + fn split_whitespace(&self) -> SplitWhitespace { fn is_not_empty(s: &&str) -> bool { !s.is_empty() } let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer fn is_whitespace(c: char) -> bool { c.is_whitespace() } let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer - Words { inner: self.split(is_whitespace).filter(is_not_empty) } + SplitWhitespace { inner: self.split(is_whitespace).filter(is_not_empty) } } #[inline] @@ -545,11 +560,11 @@ impl Iterator for Utf16Encoder where I: Iterator { } } -impl<'a> Iterator for Words<'a> { +impl<'a> Iterator for SplitWhitespace<'a> { type Item = &'a str; fn next(&mut self) -> Option<&'a str> { self.inner.next() } } -impl<'a> DoubleEndedIterator for Words<'a> { +impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() } } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 334f05fb36fa8..17053e4f10ad3 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -274,7 +274,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { }; // Transform the contents of the header into a hyphenated string - let id = s.words().map(|s| s.to_ascii_lowercase()) + let id = s.split_whitespace().map(|s| s.to_ascii_lowercase()) .collect::>().connect("-"); // This is a terrible hack working around how hoedown gives us rendered diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4389b66b52a0e..9c393d6f89737 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -31,7 +31,6 @@ #![feature(std_misc)] #![feature(test)] #![feature(unicode)] -#![feature(str_words)] #![feature(path_ext)] #![feature(path_relative_from)] #![feature(slice_patterns)] @@ -240,7 +239,7 @@ pub fn main_args(args: &[String]) -> isize { let test_args = matches.opt_strs("test-args"); let test_args: Vec = test_args.iter() - .flat_map(|s| s.words()) + .flat_map(|s| s.split_whitespace()) .map(|s| s.to_string()) .collect(); @@ -404,13 +403,13 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche } clean::NameValue(ref x, ref value) if "passes" == *x => { - for pass in value.words() { + for pass in value.split_whitespace() { passes.push(pass.to_string()); } } clean::NameValue(ref x, ref value) if "plugins" == *x => { - for p in value.words() { + for p in value.split_whitespace() { plugins.push(p.to_string()); } } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index fc5be67d4a9e5..baa6493533d29 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -2057,7 +2057,7 @@ impl> Builder { } } -/// Decodes a json value from an `&mut old_io::Reader` +/// Decodes a json value from an `&mut io::Read` pub fn from_reader(rdr: &mut Read) -> Result { let mut contents = Vec::new(); match rdr.read_to_end(&mut contents) { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index b1e14bf8f52a7..9ba90c470f8ae 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -914,33 +914,6 @@ impl HashMap IterMut { inner: self.table.iter_mut() } } - /// Creates a consuming iterator, that is, one that moves each key-value - /// pair out of the map in arbitrary order. The map cannot be used after - /// calling this. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Not possible with .iter() - /// let vec: Vec<(&str, isize)> = map.into_iter().collect(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } - let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; - - IntoIter { - inner: self.table.into_iter().map(last_two) - } - } - /// Gets the given key's corresponding entry in the map for in-place manipulation. #[stable(feature = "rust1", since = "1.0.0")] pub fn entry(&mut self, key: K) -> Entry { @@ -1388,8 +1361,30 @@ impl IntoIterator for HashMap type Item = (K, V); type IntoIter = IntoIter; + /// Creates a consuming iterator, that is, one that moves each key-value + /// pair out of the map in arbitrary order. The map cannot be used after + /// calling this. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// // Not possible with .iter() + /// let vec: Vec<(&str, isize)> = map.into_iter().collect(); + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } + let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; + + IntoIter { + inner: self.table.into_iter().map(last_two) + } } } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 82109900bf2af..f7e43b38539f1 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -269,34 +269,6 @@ impl HashSet Iter { iter: self.map.keys() } } - /// Creates a consuming iterator, that is, one that moves each value out - /// of the set in arbitrary order. The set cannot be used after calling - /// this. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a".to_string()); - /// set.insert("b".to_string()); - /// - /// // Not possible to collect to a Vec with a regular `.iter()`. - /// let v: Vec = set.into_iter().collect(); - /// - /// // Will print in an arbitrary order. - /// for x in v.iter() { - /// println!("{}", x); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn first((a, _): (A, B)) -> A { a } - let first: fn((T, ())) -> T = first; - - IntoIter { iter: self.map.into_iter().map(first) } - } - /// Visit the values representing the difference. /// /// # Examples @@ -848,8 +820,31 @@ impl IntoIterator for HashSet type Item = T; type IntoIter = IntoIter; + /// Creates a consuming iterator, that is, one that moves each value out + /// of the set in arbitrary order. The set cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashSet; + /// let mut set = HashSet::new(); + /// set.insert("a".to_string()); + /// set.insert("b".to_string()); + /// + /// // Not possible to collect to a Vec with a regular `.iter()`. + /// let v: Vec = set.into_iter().collect(); + /// + /// // Will print in an arbitrary order. + /// for x in v.iter() { + /// println!("{}", x); + /// } + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + fn first((a, _): (A, B)) -> A { a } + let first: fn((T, ())) -> T = first; + + IntoIter { iter: self.map.into_iter().map(first) } } } diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index c69df6435c498..8ca462f5a3870 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -259,19 +259,14 @@ mod dl { #[cfg(target_os = "windows")] mod dl { + use prelude::v1::*; + use ffi::OsStr; - use iter::Iterator; use libc; use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED; - use ops::FnOnce; use sys::os; use os::windows::prelude::*; - use option::Option::{self, Some, None}; use ptr; - use result::Result; - use result::Result::{Ok, Err}; - use string::String; - use vec::Vec; use sys::c::compat::kernel32::SetThreadErrorMode; pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 3ed891d024f75..114d0dd79a0a3 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -18,7 +18,6 @@ use prelude::v1::*; -use iter::IntoIterator; use error::Error; use ffi::{OsStr, OsString}; use fmt; diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index e8cdee9aca499..b5dfbf796d3bc 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -706,7 +706,7 @@ pub fn remove_file>(path: P) -> io::Result<()> { /// Given a path, query the file system to get information about a file, /// directory, etc. /// -/// This function will traverse soft links to query information about the +/// This function will traverse symbolic links to query information about the /// destination file. /// /// # Examples @@ -820,9 +820,13 @@ pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( fs_imp::link(src.as_ref(), dst.as_ref()) } -/// Creates a new soft link on the filesystem. +/// Creates a new symbolic link on the filesystem. /// -/// The `dst` path will be a soft link pointing to the `src` path. +/// The `dst` path will be a symbolic link pointing to the `src` path. +/// On Windows, this will be a file symlink, not a directory symlink; +/// for this reason, the platform-specific `std::os::unix::fs::symlink` +/// and `std::os::windows::fs::{symlink_file, symlink_dir}` should be +/// used instead to make the intent explicit. /// /// # Examples /// @@ -834,17 +838,20 @@ pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// # Ok(()) /// # } /// ``` +#[deprecated(since = "1.0.0", + reason = "replaced with std::os::unix::fs::symlink and \ + std::os::windows::fs::{symlink_file, symlink_dir}")] #[stable(feature = "rust1", since = "1.0.0")] pub fn soft_link, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { fs_imp::symlink(src.as_ref(), dst.as_ref()) } -/// Reads a soft link, returning the file that the link points to. +/// Reads a symbolic link, returning the file that the link points to. /// /// # Errors /// /// This function will return an error on failure. Failure conditions include -/// reading a file that does not exist or reading a file that is not a soft +/// reading a file that does not exist or reading a file that is not a symbolic /// link. /// /// # Examples @@ -937,8 +944,8 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// Removes a directory at this path, after removing all its contents. Use /// carefully! /// -/// This function does **not** follow soft links and it will simply remove the -/// soft link itself. +/// This function does **not** follow symbolic links and it will simply remove the +/// symbolic link itself. /// /// # Errors /// diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index a498e634185f2..11b057d0094ae 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -19,7 +19,6 @@ use rt::{backtrace, unwind}; use sys::stdio::Stderr; use thread; -// Defined in this module instead of old_io::stdio so that the unwinding thread_local! { pub static LOCAL_STDERR: RefCell>> = { RefCell::new(None) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 1148c7bc3cfdd..e8052041aeb30 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -103,7 +103,7 @@ use core::prelude::*; use ascii::*; use borrow::{Borrow, IntoCow, ToOwned, Cow}; use cmp; -use iter::{self, IntoIterator}; +use iter; use mem; use ops::{self, Deref}; use string::String; diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index c93fc13284b44..6dc11c505a914 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -26,17 +26,19 @@ #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use boxed::Box; #[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] pub use borrow::ToOwned; +#[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use clone::Clone; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; -#[unstable(feature = "convert")] +#[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From}; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use iter::DoubleEndedIterator; +#[doc(no_inline)] pub use default::Default; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use iter::ExactSizeIterator; +#[doc(no_inline)] pub use iter::{Iterator, Extend, IntoIterator}; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use iter::{Iterator, Extend}; +#[doc(no_inline)] pub use iter::{DoubleEndedIterator, ExactSizeIterator}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use option::Option::{self, Some, None}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 63e665ea6984b..56a952e6a7ef6 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -35,7 +35,7 @@ use borrow::Cow; use cmp; use fmt; use hash::{Hash, Hasher}; -use iter::{FromIterator, IntoIterator}; +use iter::FromIterator; use mem; use ops; use slice; diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index 032fd33b1d348..9504fe6369788 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -189,8 +189,12 @@ pub mod ffi { #[unstable(feature = "fs_ext", reason = "may want a more useful mode abstraction")] pub mod fs { + use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; use fs::{Permissions, OpenOptions}; + use path::Path; + use convert::AsRef; + use io; /// Unix-specific extensions to `Permissions` pub trait PermissionsExt { @@ -220,6 +224,36 @@ pub mod fs { self.as_inner_mut().mode(mode); self } } + + /// Creates a new symbolic link on the filesystem. + /// + /// The `dst` path will be a symbolic link pointing to the `src` path. + /// + /// # Note + /// + /// On Windows, you must specify whether a symbolic link points to a file + /// or directory. Use `os::windows::fs::symlink_file` to create a + /// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a + /// symbolic link to a directory. Additionally, the process must have + /// `SeCreateSymbolicLinkPrivilege` in order to be able to create a + /// symbolic link. + /// + /// # Examples + /// + /// ``` + /// #![feature(fs_ext)] + /// use std::os::unix::fs; + /// + /// # fn foo() -> std::io::Result<()> { + /// try!(fs::symlink("a.txt", "b.txt")); + /// # Ok(()) + /// # } + /// ``` + pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> + { + sys::fs2::symlink(src.as_ref(), dst.as_ref()) + } + } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/sys/unix/helper_signal.rs b/src/libstd/sys/unix/helper_signal.rs deleted file mode 100644 index fe0ede80fc663..0000000000000 --- a/src/libstd/sys/unix/helper_signal.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 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. - -#![allow(deprecated)] - -use libc; -use sys::os; - -use sys::fs::FileDesc; - -pub type signal = libc::c_int; - -pub fn new() -> (signal, signal) { - let (a, b) = unsafe { os::pipe().unwrap() }; - (a.unwrap(), b.unwrap()) -} - -pub fn signal(fd: libc::c_int) { - FileDesc::new(fd, false).write(&[0]).unwrap(); -} - -pub fn close(fd: libc::c_int) { - let _fd = FileDesc::new(fd, true); -} diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 45f389f0aebf8..331bfbfff36f9 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -54,6 +54,8 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; pub const FSCTL_GET_REPARSE_POINT: libc::DWORD = 0x900a8; pub const IO_REPARSE_TAG_SYMLINK: libc::DWORD = 0xa000000c; +pub const SYMBOLIC_LINK_FLAG_DIRECTORY: libc::DWORD = 0x1; + // Note that these are not actually HANDLEs, just values to pass to GetStdHandle pub const STD_INPUT_HANDLE: libc::DWORD = -10i32 as libc::DWORD; pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index 90548dcefb483..eac6496870eab 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -191,7 +191,11 @@ pub mod ffi { #[unstable(feature = "fs_ext", reason = "may require more thought/methods")] pub mod fs { use fs::OpenOptions; + use sys; use sys_common::AsInnerMut; + use path::Path; + use convert::AsRef; + use io; /// Windows-specific extensions to `OpenOptions` pub trait OpenOptionsExt { @@ -235,6 +239,50 @@ pub mod fs { self.as_inner_mut().share_mode(access); self } } + + /// Creates a new file symbolic link on the filesystem. + /// + /// The `dst` path will be a file symbolic link pointing to the `src` + /// path. + /// + /// # Examples + /// + /// ```ignore + /// #![feature(fs_ext)] + /// use std::os::windows::fs; + /// + /// # fn foo() -> std::io::Result<()> { + /// try!(fs::symlink_file("a.txt", "b.txt")); + /// # Ok(()) + /// # } + /// ``` + pub fn symlink_file, Q: AsRef>(src: P, dst: Q) + -> io::Result<()> + { + sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false) + } + + /// Creates a new directory symlink on the filesystem. + /// + /// The `dst` path will be a directory symbolic link pointing to the `src` + /// path. + /// + /// # Examples + /// + /// ```ignore + /// #![feature(fs_ext)] + /// use std::os::windows::fs; + /// + /// # fn foo() -> std::io::Result<()> { + /// try!(fs::symlink_file("a", "b")); + /// # Ok(()) + /// # } + /// ``` + pub fn symlink_dir, Q: AsRef> (src: P, dst: Q) + -> io::Result<()> + { + sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true) + } } /// A prelude for conveniently writing platform-specific code. diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index a9ab73feed8d2..5ac9a0ace5801 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -12,7 +12,6 @@ use core::prelude::*; use io::prelude::*; use os::windows::prelude::*; -use default::Default; use ffi::OsString; use fmt; use io::{self, Error, SeekFrom}; @@ -412,11 +411,16 @@ pub fn readlink(p: &Path) -> io::Result { } pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { + symlink_inner(src, dst, false) +} + +pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { use sys::c::compat::kernel32::CreateSymbolicLinkW; let src = to_utf16(src); let dst = to_utf16(dst); + let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 }; try!(cvt(unsafe { - CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL + CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as libc::BOOL })); Ok(()) } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 0ad75c5ec8cbc..78f06ce5fd5d0 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -238,7 +238,7 @@ pub fn name_to_dummy_lifetime(name: Name) -> Lifetime { pub fn impl_pretty_name(trait_ref: &Option, ty: Option<&Ty>) -> Ident { let mut pretty = match ty { Some(t) => pprust::ty_to_string(t), - None => String::from_str("..") + None => String::from("..") }; match *trait_ref { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 835d0395199e4..34ad192845c58 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -25,7 +25,6 @@ use std::rc::Rc; use std::fmt; -use libc::c_uint; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -286,13 +285,12 @@ pub const NO_EXPANSION: ExpnId = ExpnId(!0); pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(!1); impl ExpnId { - pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId { - ExpnId(cookie) + pub fn from_u32(id: u32) -> ExpnId { + ExpnId(id) } - pub fn to_llvm_cookie(self) -> i32 { - let ExpnId(cookie) = self; - cookie as i32 + pub fn into_u32(self) -> u32 { + self.0 } } @@ -556,9 +554,9 @@ impl CodeMap { // FIXME #12884: no efficient/safe way to remove from the start of a string // and reuse the allocation. let mut src = if src.starts_with("\u{feff}") { - String::from_str(&src[3..]) + String::from(&src[3..]) } else { - String::from_str(&src[..]) + String::from(&src[..]) }; // Append '\n' in case it's not already there. @@ -593,8 +591,8 @@ impl CodeMap { pub fn new_imported_filemap(&self, filename: FileName, source_len: usize, - file_local_lines: Vec, - file_local_multibyte_chars: Vec) + mut file_local_lines: Vec, + mut file_local_multibyte_chars: Vec) -> Rc { let mut files = self.files.borrow_mut(); let start_pos = match files.last() { @@ -605,19 +603,21 @@ impl CodeMap { let end_pos = Pos::from_usize(start_pos + source_len); let start_pos = Pos::from_usize(start_pos); - let lines = file_local_lines.map_in_place(|pos| pos + start_pos); - let multibyte_chars = file_local_multibyte_chars.map_in_place(|mbc| MultiByteChar { - pos: mbc.pos + start_pos, - bytes: mbc.bytes - }); + for pos in &mut file_local_lines { + *pos = *pos + start_pos; + } + + for mbc in &mut file_local_multibyte_chars { + mbc.pos = mbc.pos + start_pos; + } let filemap = Rc::new(FileMap { name: filename, src: None, start_pos: start_pos, end_pos: end_pos, - lines: RefCell::new(lines), - multibyte_chars: RefCell::new(multibyte_chars), + lines: RefCell::new(file_local_lines), + multibyte_chars: RefCell::new(file_local_multibyte_chars), }); files.push(filemap.clone()); diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 489a7721d7ba7..366806bc19b49 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -284,8 +284,15 @@ impl<'a> fold::Folder for CfgAttrFolder<'a> { return fold::noop_fold_attribute(attr, self); } - let (cfg, mi) = match attr.meta_item_list() { - Some([ref cfg, ref mi]) => (cfg, mi), + let attr_list = match attr.meta_item_list() { + Some(attr_list) => attr_list, + None => { + self.diag.span_err(attr.span, "expected `#[cfg_attr(, )]`"); + return None; + } + }; + let (cfg, mi) = match (attr_list.len(), attr_list.get(0), attr_list.get(1)) { + (2, Some(cfg), Some(mi)) => (cfg, mi), _ => { self.diag.span_err(attr.span, "expected `#[cfg_attr(, )]`"); return None; diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 620a8927134ba..a7453636c445c 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -644,7 +644,7 @@ fn highlight_lines(err: &mut EmitterWriter, } try!(write!(&mut err.dst, "{}", s)); - let mut s = String::from_str("^"); + let mut s = String::from("^"); let count = match lastc { // Most terminals have a tab stop every eight columns by default '\t' => 8 - col%8, diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 6fcf39f0b174b..6de4edafa0bf5 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -54,8 +54,8 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box { - let code = match token_tree { - [ast::TtToken(_, token::Ident(code, _))] => code, + let code = match (token_tree.len(), token_tree.get(0)) { + (1, Some(&ast::TtToken(_, token::Ident(code, _)))) => code, _ => unreachable!() }; with_used_diagnostics(|diagnostics| { @@ -77,20 +77,25 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, )); } }); - MacEager::expr(quote_expr!(ecx, ())) + MacEager::expr(ecx.expr_tuple(span, Vec::new())) } pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box { - let (code, description) = match token_tree { - [ast::TtToken(_, token::Ident(ref code, _))] => { + let (code, description) = match ( + token_tree.len(), + token_tree.get(0), + token_tree.get(1), + token_tree.get(2) + ) { + (1, Some(&ast::TtToken(_, token::Ident(ref code, _))), None, None) => { (code, None) }, - [ast::TtToken(_, token::Ident(ref code, _)), - ast::TtToken(_, token::Comma), - ast::TtToken(_, token::Literal(token::StrRaw(description, _), None))] => { + (3, Some(&ast::TtToken(_, token::Ident(ref code, _))), + Some(&ast::TtToken(_, token::Comma)), + Some(&ast::TtToken(_, token::Literal(token::StrRaw(description, _), None)))) => { (code, Some(description)) } _ => unreachable!() @@ -123,15 +128,23 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, let sym = Ident::new(token::gensym(&( "__register_diagnostic_".to_string() + &token::get_ident(*code) ))); - MacEager::items(SmallVector::many(vec![quote_item!(ecx, mod $sym {}).unwrap()])) + MacEager::items(SmallVector::many(vec![ + ecx.item_mod( + span, + span, + sym, + Vec::new(), + Vec::new() + ) + ])) } pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box { - let name = match token_tree { - [ast::TtToken(_, token::Ident(ref name, _))] => name, + let name = match (token_tree.len(), token_tree.get(0)) { + (1, Some(&ast::TtToken(_, token::Ident(ref name, _)))) => name, _ => unreachable!() }; @@ -148,7 +161,37 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, (descriptions.len(), ecx.expr_vec(span, descriptions)) }); - MacEager::items(SmallVector::many(vec![quote_item!(ecx, - pub static $name: [(&'static str, &'static str); $count] = $expr; - ).unwrap()])) + let static_ = ecx.lifetime(span, ecx.name_of("'static")); + let ty_str = ecx.ty_rptr( + span, + ecx.ty_ident(span, ecx.ident_of("str")), + Some(static_), + ast::MutImmutable, + ); + + let ty = ecx.ty( + span, + ast::TyFixedLengthVec( + ecx.ty( + span, + ast::TyTup(vec![ty_str.clone(), ty_str]) + ), + ecx.expr_usize(span, count), + ), + ); + + MacEager::items(SmallVector::many(vec![ + P(ast::Item { + ident: name.clone(), + attrs: Vec::new(), + id: ast::DUMMY_NODE_ID, + node: ast::ItemStatic( + ty, + ast::MutImmutable, + expr, + ), + vis: ast::Public, + span: span, + }) + ])) } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 55afac1a1de43..50ab430f148ca 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -262,10 +262,10 @@ macro_rules! make_MacEager { impl MacEager { $( pub fn $fld(v: $t) -> Box { - box MacEager { + Box::new(MacEager { $fld: Some(v), ..Default::default() - } + }) } )* } @@ -331,7 +331,7 @@ impl DummyResult { /// Use this as a return value after hitting any errors and /// calling `span_err`. pub fn any(sp: Span) -> Box { - box DummyResult { expr_only: false, span: sp } + Box::new(DummyResult { expr_only: false, span: sp }) } /// Create a default MacResult that can only be an expression. @@ -340,7 +340,7 @@ impl DummyResult { /// if an error is encountered internally, the user will receive /// an error that they also used it in the wrong place. pub fn expr(sp: Span) -> Box { - box DummyResult { expr_only: true, span: sp } + Box::new(DummyResult { expr_only: true, span: sp }) } /// A plain dummy expression. diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index b2a4ef1dafbc8..94cc0d9c493f2 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -106,8 +106,8 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, // } let new = { - let other_f = match other_fs { - [ref o_f] => o_f, + let other_f = match (other_fs.len(), other_fs.get(0)) { + (1, Some(o_f)) => o_f, _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), }; diff --git a/src/libsyntax/ext/deriving/cmp/partial_eq.rs b/src/libsyntax/ext/deriving/cmp/partial_eq.rs index f02e5ee14126d..61eb81c6755e2 100644 --- a/src/libsyntax/ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax/ext/deriving/cmp/partial_eq.rs @@ -29,8 +29,8 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, cs_fold( true, // use foldl |cx, span, subexpr, self_f, other_fs| { - let other_f = match other_fs { - [ref o_f] => o_f, + let other_f = match (other_fs.len(), other_fs.get(0)) { + (1, Some(o_f)) => o_f, _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") }; @@ -46,8 +46,8 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, cs_fold( true, // use foldl |cx, span, subexpr, self_f, other_fs| { - let other_f = match other_fs { - [ref o_f] => o_f, + let other_f = match (other_fs.len(), other_fs.get(0)) { + (1, Some(o_f)) => o_f, _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") }; diff --git a/src/libsyntax/ext/deriving/cmp/partial_ord.rs b/src/libsyntax/ext/deriving/cmp/partial_ord.rs index 9da2db25f7ea2..dbb779decace2 100644 --- a/src/libsyntax/ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax/ext/deriving/cmp/partial_ord.rs @@ -47,7 +47,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering)); let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, - vec![box ordering_ty], + vec![Box::new(ordering_ty)], true)); let inline = cx.meta_word(span, InternedString::new("inline")); @@ -150,8 +150,8 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, // } let new = { - let other_f = match other_fs { - [ref o_f] => o_f, + let other_f = match (other_fs.len(), other_fs.get(0)) { + (1, Some(o_f)) => o_f, _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), }; @@ -208,8 +208,8 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, get use the binops to avoid auto-deref dereferencing too many layers of pointers, if the type includes pointers. */ - let other_f = match other_fs { - [ref o_f] => o_f, + let other_f = match (other_fs.len(), other_fs.get(0)) { + (1, Some(o_f)) => o_f, _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") }; diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 14f0004101c81..0b31f06f87d06 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -68,14 +68,14 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, vec!(), true)))) }, explicit_self: None, - args: vec!(Ptr(box Literal(Path::new_local("__D")), + args: vec!(Ptr(Box::new(Literal(Path::new_local("__D"))), Borrowed(None, MutMutable))), ret_ty: Literal(Path::new_( pathvec_std!(cx, core::result::Result), None, - vec!(box Self_, box Literal(Path::new_( + vec!(Box::new(Self_), Box::new(Literal(Path::new_( vec!["__D", "Error"], None, vec![], false - ))), + )))), true )), attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 175f986f6dda8..92944d649332f 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -144,14 +144,14 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, vec!(), true)))) }, explicit_self: borrowed_explicit_self(), - args: vec!(Ptr(box Literal(Path::new_local("__S")), + args: vec!(Ptr(Box::new(Literal(Path::new_local("__S"))), Borrowed(None, MutMutable))), ret_ty: Literal(Path::new_( pathvec_std!(cx, core::result::Result), None, - vec!(box Tuple(Vec::new()), box Literal(Path::new_( + vec!(Box::new(Tuple(Vec::new())), Box::new(Literal(Path::new_( vec!["__S", "Error"], None, vec![], false - ))), + )))), true )), attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 4685b4b295417..4c05cd973ff6f 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -807,7 +807,7 @@ impl<'a> MethodDef<'a> { Self_ if nonstatic => { self_args.push(arg_expr); } - Ptr(box Self_, _) if nonstatic => { + Ptr(ref ty, _) if **ty == Self_ && nonstatic => { self_args.push(cx.expr_deref(trait_.span, arg_expr)) } _ => { @@ -1103,7 +1103,7 @@ impl<'a> MethodDef<'a> { subpats.push(p); idents }; - for self_arg_name in self_arg_names.tail() { + for self_arg_name in &self_arg_names[1..] { let (p, idents) = mk_self_pat(cx, &self_arg_name[..]); subpats.push(p); self_pats_idents.push(idents); diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index ec13b86a8ae2e..9e8e68c0b8cce 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -24,7 +24,7 @@ use parse::token::special_idents; use ptr::P; /// The types of pointers -#[derive(Clone)] +#[derive(Clone, Eq, PartialEq)] pub enum PtrTy<'a> { /// &'lifetime mut Borrowed(Option<&'a str>, ast::Mutability), @@ -34,7 +34,7 @@ pub enum PtrTy<'a> { /// A path, e.g. `::std::option::Option::` (global). Has support /// for type parameters and a lifetime. -#[derive(Clone)] +#[derive(Clone, Eq, PartialEq)] pub struct Path<'a> { pub path: Vec<&'a str> , pub lifetime: Option<&'a str>, @@ -85,7 +85,7 @@ impl<'a> Path<'a> { } /// A type. Supports pointers, Self, and literals -#[derive(Clone)] +#[derive(Clone, Eq, PartialEq)] pub enum Ty<'a> { Self_, /// &/Box/ Ty @@ -109,7 +109,7 @@ pub fn borrowed_explicit_self<'r>() -> Option>> { } pub fn borrowed_self<'r>() -> Ty<'r> { - borrowed(box Self_) + borrowed(Box::new(Self_)) } pub fn nil_ty<'r>() -> Ty<'r> { diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 2f6734b1a1433..b9835eda791f7 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -41,7 +41,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, vec![path_std!(cx, core::hash::Hasher)])], }, explicit_self: borrowed_explicit_self(), - args: vec!(Ptr(box Literal(arg), Borrowed(None, MutMutable))), + args: vec!(Ptr(Box::new(Literal(arg)), Borrowed(None, MutMutable))), ret_ty: nil_ty(), attributes: vec![], combine_substructure: combine_substructure(Box::new(|a, b, c| { @@ -56,8 +56,8 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, } fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P { - let state_expr = match substr.nonself_args { - [ref state_expr] => state_expr, + let state_expr = match (substr.nonself_args.len(), substr.nonself_args.get(0)) { + (1, Some(o_f)) => o_f, _ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`") }; let call_hash = |span, thing_expr| { diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 625f759fcedf8..a972cfe135511 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -40,7 +40,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, args: vec!(Literal(path_local!(i64))), ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, - vec!(box Self_), + vec!(Box::new(Self_)), true)), // #[inline] liable to cause code-bloat attributes: attrs.clone(), @@ -55,7 +55,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, args: vec!(Literal(path_local!(u64))), ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, - vec!(box Self_), + vec!(Box::new(Self_)), true)), // #[inline] liable to cause code-bloat attributes: attrs, @@ -71,8 +71,8 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, } fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P { - let n = match substr.nonself_args { - [ref n] => n, + let n = match (substr.nonself_args.len(), substr.nonself_args.get(0)) { + (1, Some(o_f)) => o_f, _ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(FromPrimitive)`") }; diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index f3b0e8a768126..3ce1f6f12ceab 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -25,7 +25,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, push: &mut FnMut(P)) { // &mut ::std::fmt::Formatter - let fmtr = Ptr(box Literal(path_std!(cx, core::fmt::Formatter)), + let fmtr = Ptr(Box::new(Literal(path_std!(cx, core::fmt::Formatter))), Borrowed(None, ast::MutMutable)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 0945f8dd02103..d1db956adb3f5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1962,8 +1962,8 @@ foo_module!(); "xx" == string }).collect(); let cxbinds: &[&ast::Ident] = &cxbinds[..]; - let cxbind = match cxbinds { - [b] => b, + let cxbind = match (cxbinds.len(), cxbinds.get(0)) { + (1, Some(b)) => *b, _ => panic!("expected just one binding for ext_cx") }; let resolved_binding = mtwt::resolve(*cxbind); diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index d91659bafe4f0..08bb4ca106486 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -128,7 +128,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree } } - box ExpandResult { p: p } + Box::new(ExpandResult { p: p }) } // include_str! : read the given file, insert it as a literal string expr diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index 3fcc6a8d69241..646e6fec40553 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -28,12 +28,11 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt, return base::DummyResult::any(sp); } - - match tt { - [ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::True) => { + match (tt.len(), tt.first()) { + (1, Some(&ast::TtToken(_, ref tok))) if tok.is_keyword(keywords::True) => { cx.set_trace_macros(true); } - [ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::False) => { + (1, Some(&ast::TtToken(_, ref tok))) if tok.is_keyword(keywords::False) => { cx.set_trace_macros(false); } _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"), diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 58df4038403a6..5521c68e75c69 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -165,7 +165,7 @@ pub fn initial_matcher_pos(ms: Rc>, sep: Option, lo: ByteP -> Box { let match_idx_hi = count_names(&ms[..]); let matches: Vec<_> = (0..match_idx_hi).map(|_| Vec::new()).collect(); - box MatcherPos { + Box::new(MatcherPos { stack: vec![], top_elts: TtSeq(ms), sep: sep, @@ -176,7 +176,7 @@ pub fn initial_matcher_pos(ms: Rc>, sep: Option, lo: ByteP match_cur: 0, match_hi: match_idx_hi, sp_lo: lo - } + }) } /// NamedMatch is a pattern-match result for a single token::MATCH_NONTERMINAL: @@ -396,7 +396,7 @@ pub fn parse(sess: &ParseSess, let matches: Vec<_> = (0..ei.matches.len()) .map(|_| Vec::new()).collect(); let ei_t = ei; - cur_eis.push(box MatcherPos { + cur_eis.push(Box::new(MatcherPos { stack: vec![], sep: seq.separator.clone(), idx: 0, @@ -407,7 +407,7 @@ pub fn parse(sess: &ParseSess, up: Some(ei_t), sp_lo: sp.lo, top_elts: Tt(TtSequence(sp, seq)), - }); + })); } TtToken(_, MatchNt(..)) => { // Built-in nonterminals never start with these tokens, @@ -533,7 +533,7 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { "ty" => token::NtTy(p.parse_ty()), // this could be handled like a token, since it is one "ident" => match p.token { - token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(box sn,b) } + token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(Box::new(sn),b) } _ => { let token_str = pprust::token_to_string(&p.token); panic!(p.fatal(&format!("expected ident, found {}", @@ -541,7 +541,7 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { } }, "path" => { - token::NtPath(box panictry!(p.parse_path(LifetimeAndTypesWithoutColons))) + token::NtPath(Box::new(panictry!(p.parse_path(LifetimeAndTypesWithoutColons)))) } "meta" => token::NtMeta(p.parse_meta_item()), _ => { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 730da6cc59419..27a00290ee01e 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -192,7 +192,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, panictry!(p.check_unknown_macro_variable()); // Let the context choose how to interpret the result. // Weird, but useful for X-macros. - return box ParserAnyMacro { + return Box::new(ParserAnyMacro { parser: RefCell::new(p), // Pass along the original expansion site and the name of the macro @@ -200,7 +200,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // macro leaves unparsed tokens. site_span: sp, macro_ident: name - } + }) } Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo { best_fail_spot = sp; @@ -281,12 +281,12 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, _ => cx.span_bug(def.span, "wrong-structured rhs") }; - let exp: Box<_> = box MacroRulesMacroExpander { + let exp: Box<_> = Box::new(MacroRulesMacroExpander { name: def.ident, imported_from: def.imported_from, lhses: lhses, rhses: rhses, - }; + }); NormalTT(exp, Some(def.span), def.allow_internal_unstable) } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index e39b46a2d3e11..368a9f0c27e56 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -294,9 +294,9 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { // sidestep the interpolation tricks for ident because // (a) idents can be in lots of places, so it'd be a pain // (b) we actually can, since it's a token. - MatchedNonterminal(NtIdent(box sn, b)) => { + MatchedNonterminal(NtIdent(ref sn, b)) => { r.cur_span = sp; - r.cur_tok = token::Ident(sn, b); + r.cur_tok = token::Ident(**sn, b); return ret_val; } MatchedNonterminal(ref other_whole_nt) => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index d7033ce7e48a4..8ba36cefc65dd 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -677,10 +677,10 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)), token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)), token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)), - token::NtIdent(box id, is_mod_name) => - token::NtIdent(box fld.fold_ident(id), is_mod_name), + token::NtIdent(id, is_mod_name) => + token::NtIdent(Box::new(fld.fold_ident(*id)), is_mod_name), token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)), - token::NtPath(box path) => token::NtPath(box fld.fold_path(path)), + token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))), token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&*tt))), } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 3f36d0e8eda0f..d8beeb6a5503b 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -25,19 +25,13 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] -#![feature(box_patterns)] -#![feature(box_syntax)] #![feature(collections)] #![feature(core)] #![feature(libc)] -#![feature(quote, unsafe_destructor)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(unicode)] -#![feature(path_ext)] #![feature(str_char)] -#![feature(into_cow)] -#![feature(slice_patterns)] extern crate arena; extern crate fmt_macros; @@ -98,6 +92,7 @@ pub mod parse; pub mod ptr; pub mod show_span; pub mod std_inject; +pub mod str; pub mod test; pub mod visit; diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index bda01d5a6541c..fb3a96f4c2887 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -13,11 +13,12 @@ pub use self::CommentStyle::*; use ast; use codemap::{BytePos, CharPos, CodeMap, Pos}; use diagnostic; -use parse::lexer::{is_whitespace, Reader}; -use parse::lexer::{StringReader, TokenAndSpan}; use parse::lexer::is_block_doc_comment; +use parse::lexer::{StringReader, TokenAndSpan}; +use parse::lexer::{is_whitespace, Reader}; use parse::lexer; use print::pprust; +use str::char_at; use std::io::Read; use std::usize; @@ -209,7 +210,7 @@ fn all_whitespace(s: &str, col: CharPos) -> Option { let mut col = col.to_usize(); let mut cursor: usize = 0; while col > 0 && cursor < len { - let ch = s.char_at(cursor); + let ch = char_at(s, cursor); if !ch.is_whitespace() { return None; } @@ -246,7 +247,7 @@ fn read_block_comment(rdr: &mut StringReader, rdr.bump(); rdr.bump(); - let mut curr_line = String::from_str("/*"); + let mut curr_line = String::from("/*"); // doc-comments are not really comments, they are attributes if (rdr.curr_is('*') && !rdr.nextch_is('*')) || rdr.curr_is('!') { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index f891318659a87..8e37b983e21e0 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -13,10 +13,11 @@ use codemap::{BytePos, CharPos, CodeMap, Pos, Span}; use codemap; use diagnostic::SpanHandler; use ext::tt::transcribe::tt_next_token; -use parse::token; use parse::token::str_to_ident; +use parse::token; +use str::char_at; -use std::borrow::{IntoCow, Cow}; +use std::borrow::Cow; use std::char; use std::fmt; use std::mem::replace; @@ -289,11 +290,11 @@ impl<'a> StringReader<'a> { s: &'b str, errmsg: &'b str) -> Cow<'b, str> { let mut i = 0; while i < s.len() { - let ch = s.char_at(i); + let ch = char_at(s, i); let next = i + ch.len_utf8(); if ch == '\r' { - if next < s.len() && s.char_at(next) == '\n' { - return translate_crlf_(self, start, s, errmsg, i).into_cow(); + if next < s.len() && char_at(s, next) == '\n' { + return translate_crlf_(self, start, s, errmsg, i).into(); } let pos = start + BytePos(i as u32); let end_pos = start + BytePos(next as u32); @@ -301,19 +302,19 @@ impl<'a> StringReader<'a> { } i = next; } - return s.into_cow(); + return s.into(); fn translate_crlf_(rdr: &StringReader, start: BytePos, s: &str, errmsg: &str, mut i: usize) -> String { let mut buf = String::with_capacity(s.len()); let mut j = 0; while i < s.len() { - let ch = s.char_at(i); + let ch = char_at(s, i); let next = i + ch.len_utf8(); if ch == '\r' { if j < i { buf.push_str(&s[j..i]); } j = next; - if next >= s.len() || s.char_at(next) != '\n' { + if next >= s.len() || char_at(s, next) != '\n' { let pos = start + BytePos(i as u32); let end_pos = start + BytePos(next as u32); rdr.err_span_(pos, end_pos, errmsg); @@ -335,7 +336,7 @@ impl<'a> StringReader<'a> { if current_byte_offset < self.source_text.len() { assert!(self.curr.is_some()); let last_char = self.curr.unwrap(); - let ch = self.source_text.char_at(current_byte_offset); + let ch = char_at(&self.source_text, current_byte_offset); let next = current_byte_offset + ch.len_utf8(); let byte_offset_diff = next - current_byte_offset; self.pos = self.pos + Pos::from_usize(byte_offset_diff); @@ -357,7 +358,7 @@ impl<'a> StringReader<'a> { pub fn nextch(&self) -> Option { let offset = self.byte_offset(self.pos).to_usize(); if offset < self.source_text.len() { - Some(self.source_text.char_at(offset)) + Some(char_at(&self.source_text, offset)) } else { None } @@ -371,9 +372,9 @@ impl<'a> StringReader<'a> { let offset = self.byte_offset(self.pos).to_usize(); let s = &self.source_text[..]; if offset >= s.len() { return None } - let next = offset + s.char_at(offset).len_utf8(); + let next = offset + char_at(s, offset).len_utf8(); if next < s.len() { - Some(s.char_at(next)) + Some(char_at(s, next)) } else { None } @@ -564,7 +565,7 @@ impl<'a> StringReader<'a> { let string = if has_cr { self.translate_crlf(start_bpos, string, "bare CR not allowed in block doc-comment") - } else { string.into_cow() }; + } else { string.into() }; token::DocComment(token::intern(&string[..])) } else { token::Comment diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index f4b108c435276..1a1713a8ba632 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -16,7 +16,7 @@ use diagnostic::{SpanHandler, mk_span_handler, default_handler, Auto, FatalError use parse::attr::ParserAttr; use parse::parser::Parser; use ptr::P; - +use str::char_at; use std::cell::{Cell, RefCell}; use std::fs::File; @@ -286,7 +286,7 @@ pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc) // parsing tt's probably shouldn't require a parser at all. let cfg = Vec::new(); let srdr = lexer::StringReader::new(&sess.span_diagnostic, filemap); - let mut p1 = Parser::new(sess, cfg, box srdr); + let mut p1 = Parser::new(sess, cfg, Box::new(srdr)); panictry!(p1.parse_all_token_trees()) } @@ -295,7 +295,7 @@ pub fn tts_to_parser<'a>(sess: &'a ParseSess, tts: Vec, cfg: ast::CrateConfig) -> Parser<'a> { let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts); - let mut p = Parser::new(sess, cfg, box trdr); + let mut p = Parser::new(sess, cfg, Box::new(trdr)); panictry!(p.check_unknown_macro_variable()); p } @@ -358,7 +358,7 @@ pub mod with_hygiene { use super::lexer::make_reader_with_embedded_idents as make_reader; let cfg = Vec::new(); let srdr = make_reader(&sess.span_diagnostic, filemap); - let mut p1 = Parser::new(sess, cfg, box srdr); + let mut p1 = Parser::new(sess, cfg, Box::new(srdr)); panictry!(p1.parse_all_token_trees()) } } @@ -534,7 +534,7 @@ pub fn raw_str_lit(lit: &str) -> String { // check if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 && - first_chars.contains(&s.char_at(0)) && + first_chars.contains(&char_at(s, 0)) && s[1..].chars().all(|c| '0' <= c && c <= '9') } @@ -671,8 +671,8 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> let orig = s; let mut ty = ast::UnsuffixedIntLit(ast::Plus); - if s.char_at(0) == '0' && s.len() > 1 { - match s.char_at(1) { + if char_at(s, 0) == '0' && s.len() > 1 { + match char_at(s, 1) { 'x' => base = 16, 'o' => base = 8, 'b' => base = 2, @@ -832,28 +832,44 @@ mod test { fn string_to_tts_macro () { let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_string()); let tts: &[ast::TokenTree] = &tts[..]; - match tts { - [ast::TtToken(_, token::Ident(name_macro_rules, token::Plain)), - ast::TtToken(_, token::Not), - ast::TtToken(_, token::Ident(name_zip, token::Plain)), - ast::TtDelimited(_, ref macro_delimed)] + + match (tts.len(), tts.get(0), tts.get(1), tts.get(2), tts.get(3)) { + ( + 4, + Some(&ast::TtToken(_, token::Ident(name_macro_rules, token::Plain))), + Some(&ast::TtToken(_, token::Not)), + Some(&ast::TtToken(_, token::Ident(name_zip, token::Plain))), + Some(&ast::TtDelimited(_, ref macro_delimed)), + ) if name_macro_rules.as_str() == "macro_rules" && name_zip.as_str() == "zip" => { - match ¯o_delimed.tts[..] { - [ast::TtDelimited(_, ref first_delimed), - ast::TtToken(_, token::FatArrow), - ast::TtDelimited(_, ref second_delimed)] + let tts = ¯o_delimed.tts[..]; + match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { + ( + 3, + Some(&ast::TtDelimited(_, ref first_delimed)), + Some(&ast::TtToken(_, token::FatArrow)), + Some(&ast::TtDelimited(_, ref second_delimed)), + ) if macro_delimed.delim == token::Paren => { - match &first_delimed.tts[..] { - [ast::TtToken(_, token::Dollar), - ast::TtToken(_, token::Ident(name, token::Plain))] + let tts = &first_delimed.tts[..]; + match (tts.len(), tts.get(0), tts.get(1)) { + ( + 2, + Some(&ast::TtToken(_, token::Dollar)), + Some(&ast::TtToken(_, token::Ident(name, token::Plain))), + ) if first_delimed.delim == token::Paren && name.as_str() == "a" => {}, _ => panic!("value 3: {:?}", **first_delimed), } - match &second_delimed.tts[..] { - [ast::TtToken(_, token::Dollar), - ast::TtToken(_, token::Ident(name, token::Plain))] + let tts = &second_delimed.tts[..]; + match (tts.len(), tts.get(0), tts.get(1)) { + ( + 2, + Some(&ast::TtToken(_, token::Dollar)), + Some(&ast::TtToken(_, token::Ident(name, token::Plain))), + ) if second_delimed.delim == token::Paren && name.as_str() == "a" => {}, _ => panic!("value 4: {:?}", **second_delimed), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0515d1ae945bd..796bc2a3513f3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -78,6 +78,7 @@ use parse::PResult; use diagnostic::FatalError; use std::collections::HashSet; +use std::fs; use std::io::prelude::*; use std::mem; use std::path::{Path, PathBuf}; @@ -436,10 +437,11 @@ impl<'a> Parser<'a> { // leave it in the input Ok(()) } else { - let mut expected = edible.iter().map(|x| TokenType::Token(x.clone())) - .collect::>(); - expected.extend(inedible.iter().map(|x| TokenType::Token(x.clone()))); - expected.push_all(&*self.expected_tokens); + let mut expected = edible.iter() + .map(|x| TokenType::Token(x.clone())) + .chain(inedible.iter().map(|x| TokenType::Token(x.clone()))) + .chain(self.expected_tokens.iter().cloned()) + .collect::>(); expected.sort_by(|a, b| a.to_string().cmp(&b.to_string())); expected.dedup(); let expect = tokens_to_string(&expected[..]); @@ -490,8 +492,10 @@ impl<'a> Parser<'a> { debug!("commit_expr {:?}", e); if let ExprPath(..) = e.node { // might be unit-struct construction; check for recoverableinput error. - let mut expected = edible.iter().cloned().collect::>(); - expected.push_all(inedible); + let expected = edible.iter() + .cloned() + .chain(inedible.iter().cloned()) + .collect::>(); try!(self.check_for_erroneous_unit_struct_expecting(&expected[..])); } self.expect_one_of(edible, inedible) @@ -509,8 +513,10 @@ impl<'a> Parser<'a> { if self.last_token .as_ref() .map_or(false, |t| t.is_ident() || t.is_path()) { - let mut expected = edible.iter().cloned().collect::>(); - expected.push_all(&inedible); + let expected = edible.iter() + .cloned() + .chain(inedible.iter().cloned()) + .collect::>(); try!(self.check_for_erroneous_unit_struct_expecting(&expected)); } self.expect_one_of(edible, inedible) @@ -897,7 +903,7 @@ impl<'a> Parser<'a> { self.last_span = self.span; // Stash token for error recovery (sometimes; clone is not necessarily cheap). self.last_token = if self.token.is_ident() || self.token.is_path() { - Some(box self.token.clone()) + Some(Box::new(self.token.clone())) } else { None }; @@ -1187,7 +1193,7 @@ impl<'a> Parser<'a> { debug!("parse_trait_methods(): parsing provided method"); let (inner_attrs, body) = try!(p.parse_inner_attrs_and_block()); - attrs.push_all(&inner_attrs[..]); + attrs.extend(inner_attrs.iter().cloned()); Some(body) } @@ -1578,8 +1584,8 @@ impl<'a> Parser<'a> { token::Interpolated(token::NtPath(_)) => Some(try!(self.bump_and_get())), _ => None, }; - if let Some(token::Interpolated(token::NtPath(box path))) = found { - return Ok(path); + if let Some(token::Interpolated(token::NtPath(path))) = found { + return Ok(*path); } let lo = self.span.lo; @@ -4770,8 +4776,8 @@ impl<'a> Parser<'a> { let secondary_path_str = format!("{}/mod.rs", mod_name); let default_path = dir_path.join(&default_path_str[..]); let secondary_path = dir_path.join(&secondary_path_str[..]); - let default_exists = default_path.exists(); - let secondary_exists = secondary_path.exists(); + let default_exists = fs::metadata(&default_path).is_ok(); + let secondary_exists = fs::metadata(&secondary_path).is_ok(); if !self.owns_directory { self.span_err(id_sp, @@ -4834,7 +4840,7 @@ impl<'a> Parser<'a> { let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); match included_mod_stack.iter().position(|p| *p == path) { Some(i) => { - let mut err = String::from_str("circular modules: "); + let mut err = String::from("circular modules: "); let len = included_mod_stack.len(); for p in &included_mod_stack[i.. len] { err.push_str(&p.to_string_lossy()); diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 3fd4e31b4771e..15aaf9cf390fd 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -131,7 +131,7 @@ pub fn buf_str(toks: &[Token], assert_eq!(n, szs.len()); let mut i = left; let mut l = lim; - let mut s = string::String::from_str("["); + let mut s = string::String::from("["); while i != right && l != 0 { l -= 1; if i != left { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c51b5d039784d..5a57e09fcfff2 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -28,7 +28,7 @@ use print::pp::Breaks::{Consistent, Inconsistent}; use ptr::P; use std_inject; -use std::{ascii, mem}; +use std::ascii; use std::io::{self, Write, Read}; use std::iter; @@ -187,18 +187,13 @@ impl<'a> State<'a> { pub fn to_string(f: F) -> String where F: FnOnce(&mut State) -> io::Result<()>, { - use std::raw::TraitObject; - let mut s = rust_printer(box Vec::new()); - f(&mut s).unwrap(); - eof(&mut s.s).unwrap(); - let wr = unsafe { - // FIXME(pcwalton): A nasty function to extract the string from an `Write` - // that we "know" to be a `Vec` that works around the lack of checked - // downcasts. - let obj: &TraitObject = mem::transmute(&s.s.out); - mem::transmute::<*mut (), &Vec>(obj.data) - }; - String::from_utf8(wr.clone()).unwrap() + let mut wr = Vec::new(); + { + let mut printer = rust_printer(Box::new(&mut wr)); + f(&mut printer).unwrap(); + eof(&mut printer.s).unwrap(); + } + String::from_utf8(wr).unwrap() } pub fn binop_to_string(op: BinOpToken) -> &'static str { @@ -2799,13 +2794,13 @@ impl<'a> State<'a> { match lit.node { ast::LitStr(ref st, style) => self.print_string(&st, style), ast::LitByte(byte) => { - let mut res = String::from_str("b'"); + let mut res = String::from("b'"); res.extend(ascii::escape_default(byte).map(|c| c as char)); res.push('\''); word(&mut self.s, &res[..]) } ast::LitChar(ch) => { - let mut res = String::from_str("'"); + let mut res = String::from("'"); res.extend(ch.escape_default()); res.push('\''); word(&mut self.s, &res[..]) diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 5032cd57eeb37..83e321f110c58 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -52,7 +52,7 @@ pub struct P { /// Construct a `P` from a `T` value. pub fn P(value: T) -> P { P { - ptr: box value + ptr: Box::new(value) } } diff --git a/src/libsyntax/str.rs b/src/libsyntax/str.rs new file mode 100644 index 0000000000000..d0f47629b10e5 --- /dev/null +++ b/src/libsyntax/str.rs @@ -0,0 +1,13 @@ +// Copyright 2012-2014 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. + +pub fn char_at(s: &str, byte: usize) -> char { + s[byte..].chars().next().unwrap() +} diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index c6646fe93a21b..6adeb30a94ec4 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -15,6 +15,7 @@ use parse::new_parser_from_source_str; use parse::parser::Parser; use parse::token; use ptr::P; +use str::char_at; /// Map a string to tts, using a made-up filename: pub fn string_to_tts(source_str: String) -> Vec { @@ -96,24 +97,24 @@ pub fn matches_codepattern(a : &str, b : &str) -> bool { else if idx_a == a.len() {return false;} else if idx_b == b.len() { // maybe the stuff left in a is all ws? - if is_whitespace(a.char_at(idx_a)) { + if is_whitespace(char_at(a, idx_a)) { return scan_for_non_ws_or_end(a,idx_a) == a.len(); } else { return false; } } // ws in both given and pattern: - else if is_whitespace(a.char_at(idx_a)) - && is_whitespace(b.char_at(idx_b)) { + else if is_whitespace(char_at(a, idx_a)) + && is_whitespace(char_at(b, idx_b)) { idx_a = scan_for_non_ws_or_end(a,idx_a); idx_b = scan_for_non_ws_or_end(b,idx_b); } // ws in given only: - else if is_whitespace(a.char_at(idx_a)) { + else if is_whitespace(char_at(a, idx_a)) { idx_a = scan_for_non_ws_or_end(a,idx_a); } // *don't* silently eat ws in expected only. - else if a.char_at(idx_a) == b.char_at(idx_b) { + else if char_at(a, idx_a) == char_at(b, idx_b) { idx_a += 1; idx_b += 1; } @@ -129,7 +130,7 @@ pub fn matches_codepattern(a : &str, b : &str) -> bool { fn scan_for_non_ws_or_end(a : &str, idx: usize) -> usize { let mut i = idx; let len = a.len(); - while (i < len) && (is_whitespace(a.char_at(i))) { + while (i < len) && (is_whitespace(char_at(a, i))) { i += 1; } i diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 6b864d5294766..153f9d4a26df1 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -64,7 +64,10 @@ impl SmallVector { let result: &[T] = &[]; result } - One(ref v) => slice::ref_slice(v), + One(ref v) => { + // FIXME: Could be replaced with `slice::ref_slice(v)` when it is stable. + unsafe { slice::from_raw_parts(v, 1) } + } Many(ref vs) => vs } } diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index 01d191f30147b..3de99088da47b 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -355,11 +355,4 @@ mod test { assert_eq!(numfnames.len(), numnames.len()); assert_eq!(stringfnames.len(), stringnames.len()); } - - #[test] - #[ignore(reason = "no ncurses on buildbots, needs a bundled terminfo file to test against")] - fn test_parse() { - // FIXME #6870: Distribute a compiled file in src/tests and test there - // parse(old_io::fs_reader(&p("/usr/share/terminfo/r/rxvt-256color")).unwrap(), false); - } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 4532f5d65d870..b68b1d28b3567 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -43,7 +43,6 @@ #![feature(std_misc)] #![feature(libc)] #![feature(set_stdio)] -#![cfg_attr(test, feature(old_io))] extern crate getopts; extern crate serialize; diff --git a/src/rustllvm/ExecutionEngineWrapper.cpp b/src/rustllvm/ExecutionEngineWrapper.cpp index 8ca81ab3d68ea..7e0630fd242d3 100644 --- a/src/rustllvm/ExecutionEngineWrapper.cpp +++ b/src/rustllvm/ExecutionEngineWrapper.cpp @@ -89,12 +89,12 @@ extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine( options.NoFramePointerElim = true; ExecutionEngine *ee = - #if LLVM_VERSION_MINOR <= 5 - EngineBuilder(unwrap(mod)) - .setMCJITMemoryManager(unwrap(mref)) - #else + #if LLVM_VERSION_MINOR >= 6 EngineBuilder(std::unique_ptr(unwrap(mod))) .setMCJITMemoryManager(std::unique_ptr(unwrap(mref))) + #else + EngineBuilder(unwrap(mod)) + .setMCJITMemoryManager(unwrap(mref)) #endif .setEngineKind(EngineKind::JIT) .setErrorStr(&error_str) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index b205d87598cfe..a2ab8040198ff 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -92,9 +92,6 @@ LLVMRustCreateTargetMachine(const char *triple, TargetOptions Options; Options.PositionIndependentExecutable = PositionIndependentExecutable; Options.NoFramePointerElim = NoFramePointerElim; -#if LLVM_VERSION_MINOR < 5 - Options.EnableSegmentedStacks = EnableSegmentedStacks; -#endif Options.FloatABIType = FloatABI::Default; Options.UseSoftFloat = UseSoftFloat; if (UseSoftFloat) { @@ -128,10 +125,8 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM, PassManagerBase *PM = unwrap(PMR); #if LLVM_VERSION_MINOR >= 6 PM->add(new DataLayoutPass()); -#elif LLVM_VERSION_MINOR == 5 - PM->add(new DataLayoutPass(unwrap(M))); #else - PM->add(new DataLayout(unwrap(M))); + PM->add(new DataLayoutPass(unwrap(M))); #endif unwrap(TM)->addAnalysisPasses(*PM); } @@ -202,10 +197,8 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, raw_fd_ostream OS(path, EC, sys::fs::F_None); if (EC) ErrorInfo = EC.message(); -#elif LLVM_VERSION_MINOR >= 4 - raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None); #else - raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary); + raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None); #endif if (ErrorInfo != "") { LLVMRustSetLastError(ErrorInfo.c_str()); @@ -230,19 +223,13 @@ LLVMRustPrintModule(LLVMPassManagerRef PMR, raw_fd_ostream OS(path, EC, sys::fs::F_None); if (EC) ErrorInfo = EC.message(); -#elif LLVM_VERSION_MINOR >= 4 - raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None); #else - raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary); + raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None); #endif formatted_raw_ostream FOS(OS); -#if LLVM_VERSION_MINOR >= 5 PM->add(createPrintModulePass(FOS)); -#else - PM->add(createPrintModulePass(&FOS)); -#endif PM->run(*unwrap(M)); } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 31f75ae03b099..fe0a7b454c17d 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -412,7 +412,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable( bool isLocalToUnit, LLVMValueRef Val, LLVMMetadataRef Decl = NULL) { -#if LLVM_VERSION_MINOR == 6 +#if LLVM_VERSION_MINOR >= 6 return wrap(Builder->createGlobalVariable(unwrapDI(Context), #else return wrap(Builder->createStaticVariable(unwrapDI(Context), @@ -440,7 +440,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable( int64_t* AddrOps, unsigned AddrOpsCount, unsigned ArgNo) { -#if LLVM_VERSION_MINOR < 6 +#if LLVM_VERSION_MINOR == 5 if (AddrOpsCount > 0) { SmallVector addr_ops; llvm::Type *Int64Ty = Type::getInt64Ty(unwrap(Scope)->getContext()); @@ -707,12 +707,12 @@ extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) { extern "C" bool LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { Module *Dst = unwrap(dst); -#if LLVM_VERSION_MINOR == 5 - MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len)); - ErrorOr Src = llvm::getLazyBitcodeModule(buf, Dst->getContext()); -#else +#if LLVM_VERSION_MINOR >= 6 std::unique_ptr buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len)); ErrorOr Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext()); +#else + MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len)); + ErrorOr Src = llvm::getLazyBitcodeModule(buf, Dst->getContext()); #endif if (!Src) { LLVMRustSetLastError(Src.getError().message().c_str()); @@ -770,53 +770,74 @@ LLVMRustOpenArchive(char *path) { return ret; } -extern "C" const char* #if LLVM_VERSION_MINOR >= 6 -LLVMRustArchiveReadSection(OwningBinary *ob, char *name, size_t *size) { - - Archive *ar = ob->getBinary(); +typedef OwningBinary RustArchive; +#define GET_ARCHIVE(a) ((a)->getBinary()) #else -LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) { +typedef Archive RustArchive; +#define GET_ARCHIVE(a) (a) #endif - Archive::child_iterator child = ar->child_begin(), - end = ar->child_end(); - for (; child != end; ++child) { - ErrorOr name_or_err = child->getName(); - if (name_or_err.getError()) continue; - StringRef sect_name = name_or_err.get(); - if (sect_name.trim(" ") == name) { - StringRef buf = child->getBuffer(); - *size = buf.size(); - return buf.data(); - } - } - return NULL; +extern "C" void +LLVMRustDestroyArchive(RustArchive *ar) { + delete ar; +} + +struct RustArchiveIterator { + Archive::child_iterator cur; + Archive::child_iterator end; +}; + +extern "C" RustArchiveIterator* +LLVMRustArchiveIteratorNew(RustArchive *ra) { + Archive *ar = GET_ARCHIVE(ra); + RustArchiveIterator *rai = new RustArchiveIterator(); + rai->cur = ar->child_begin(); + rai->end = ar->child_end(); + return rai; +} + +extern "C" const Archive::Child* +LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) { + if (rai->cur == rai->end) + return NULL; + const Archive::Child &ret = *rai->cur; + return &ret; } extern "C" void -#if LLVM_VERSION_MINOR >= 6 -LLVMRustDestroyArchive(OwningBinary *ar) { -#else -LLVMRustDestroyArchive(Archive *ar) { -#endif - delete ar; +LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) { + if (rai->cur == rai->end) + return; + ++rai->cur; } extern "C" void -LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) { - GlobalValue *V = unwrap(Value); - V->setDLLStorageClass(GlobalValue::DLLExportStorageClass); +LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) { + delete rai; } -extern "C" int -LLVMVersionMinor() { - return LLVM_VERSION_MINOR; +extern "C" const char* +LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) { + ErrorOr name_or_err = child->getName(); + if (name_or_err.getError()) + return NULL; + StringRef name = name_or_err.get(); + *size = name.size(); + return name.data(); } -extern "C" int -LLVMVersionMajor() { - return LLVM_VERSION_MAJOR; +extern "C" const char* +LLVMRustArchiveChildData(Archive::Child *child, size_t *size) { + StringRef buf = child->getBuffer(); + *size = buf.size(); + return buf.data(); +} + +extern "C" void +LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) { + GlobalValue *V = unwrap(Value); + V->setDLLStorageClass(GlobalValue::DLLExportStorageClass); } // Note that the two following functions look quite similar to the diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 33dec63a728e1..8a4330acf4341 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -46,17 +46,10 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Object.h" -#if LLVM_VERSION_MINOR >= 5 #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DIBuilder.h" #include "llvm/Linker/Linker.h" -#else -#include "llvm/Assembly/PrintModulePass.h" -#include "llvm/DebugInfo.h" -#include "llvm/DIBuilder.h" -#include "llvm/Linker.h" -#endif // Used by RustMCJITMemoryManager::getPointerToNamedFunction() // to get around glibc issues. See the function for more information. diff --git a/src/test/auxiliary/linkage-visibility.rs b/src/test/auxiliary/linkage-visibility.rs index d96dfd848f3f0..6cc2d427c25dc 100644 --- a/src/test/auxiliary/linkage-visibility.rs +++ b/src/test/auxiliary/linkage-visibility.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(std_misc, old_path)] +#![feature(std_misc)] use std::dynamic_lib::DynamicLibrary; diff --git a/src/test/compile-fail/loop-labeled-break-value.rs b/src/test/compile-fail/loop-labeled-break-value.rs index e1ae3ae464f98..f0792c145d2a2 100644 --- a/src/test/compile-fail/loop-labeled-break-value.rs +++ b/src/test/compile-fail/loop-labeled-break-value.rs @@ -16,6 +16,6 @@ fn main() { let _: i32 = 'inner: loop { break 'inner }; //~ ERROR mismatched types } loop { - let _: i32 = 'inner: loop { loop { break 'inner } }; //~ ERROR mismatched types + let _: i32 = 'inner2: loop { loop { break 'inner2 } }; //~ ERROR mismatched types } } diff --git a/src/test/compile-fail/loops-reject-duplicate-labels-2.rs b/src/test/compile-fail/loops-reject-duplicate-labels-2.rs new file mode 100644 index 0000000000000..68627ecaa718f --- /dev/null +++ b/src/test/compile-fail/loops-reject-duplicate-labels-2.rs @@ -0,0 +1,51 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +// ignore-tidy-linelength + +// Issue #21633: reject duplicate loop labels in function bodies. +// +// This is testing the generalization (to the whole function body) +// discussed here: +// http://internals.rust-lang.org/t/psa-rejecting-duplicate-loop-labels/1833 + +pub fn foo() { + { 'fl: for _ in 0..10 { break; } } //~ NOTE shadowed label `'fl` declared here + { 'fl: loop { break; } } //~ WARN label name `'fl` shadows a label name that is already in scope + + { 'lf: loop { break; } } //~ NOTE shadowed label `'lf` declared here + { 'lf: for _ in 0..10 { break; } } //~ WARN label name `'lf` shadows a label name that is already in scope + + { 'wl: while 2 > 1 { break; } } //~ NOTE shadowed label `'wl` declared here + { 'wl: loop { break; } } //~ WARN label name `'wl` shadows a label name that is already in scope + + { 'lw: loop { break; } } //~ NOTE shadowed label `'lw` declared here + { 'lw: while 2 > 1 { break; } } //~ WARN label name `'lw` shadows a label name that is already in scope + + { 'fw: for _ in 0..10 { break; } } //~ NOTE shadowed label `'fw` declared here + { 'fw: while 2 > 1 { break; } } //~ WARN label name `'fw` shadows a label name that is already in scope + + { 'wf: while 2 > 1 { break; } } //~ NOTE shadowed label `'wf` declared here + { 'wf: for _ in 0..10 { break; } } //~ WARN label name `'wf` shadows a label name that is already in scope + + { 'tl: while let Some(_) = None:: { break; } } //~ NOTE shadowed label `'tl` declared here + { 'tl: loop { break; } } //~ WARN label name `'tl` shadows a label name that is already in scope + + { 'lt: loop { break; } } //~ NOTE shadowed label `'lt` declared here + { 'lt: while let Some(_) = None:: { break; } } + //~^ WARN label name `'lt` shadows a label name that is already in scope +} + +#[rustc_error] +pub fn main() { //~ ERROR compilation successful + foo(); +} diff --git a/src/test/compile-fail/loops-reject-duplicate-labels.rs b/src/test/compile-fail/loops-reject-duplicate-labels.rs new file mode 100644 index 0000000000000..15446bf642d4d --- /dev/null +++ b/src/test/compile-fail/loops-reject-duplicate-labels.rs @@ -0,0 +1,60 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +// ignore-tidy-linelength + +// Issue #21633: reject duplicate loop labels in function bodies. +// This is testing the exact cases that are in the issue description. + +fn foo() { + 'fl: for _ in 0..10 { break; } //~ NOTE shadowed label `'fl` declared here + 'fl: loop { break; } //~ WARN label name `'fl` shadows a label name that is already in scope + + 'lf: loop { break; } //~ NOTE shadowed label `'lf` declared here + 'lf: for _ in 0..10 { break; } //~ WARN label name `'lf` shadows a label name that is already in scope + + 'wl: while 2 > 1 { break; } //~ NOTE shadowed label `'wl` declared here + 'wl: loop { break; } //~ WARN label name `'wl` shadows a label name that is already in scope + + 'lw: loop { break; } //~ NOTE shadowed label `'lw` declared here + 'lw: while 2 > 1 { break; } //~ WARN label name `'lw` shadows a label name that is already in scope + + 'fw: for _ in 0..10 { break; } //~ NOTE shadowed label `'fw` declared here + 'fw: while 2 > 1 { break; } //~ WARN label name `'fw` shadows a label name that is already in scope + + 'wf: while 2 > 1 { break; } //~ NOTE shadowed label `'wf` declared here + 'wf: for _ in 0..10 { break; } //~ WARN label name `'wf` shadows a label name that is already in scope + + 'tl: while let Some(_) = None:: { break; } //~ NOTE shadowed label `'tl` declared here + 'tl: loop { break; } //~ WARN label name `'tl` shadows a label name that is already in scope + + 'lt: loop { break; } //~ NOTE shadowed label `'lt` declared here + 'lt: while let Some(_) = None:: { break; } + //~^ WARN label name `'lt` shadows a label name that is already in scope +} + +// Note however that it is okay for the same label to be reused in +// different methods of one impl, as illustrated here. + +struct S; +impl S { + fn m1(&self) { 'okay: loop { break 'okay; } } + fn m2(&self) { 'okay: loop { break 'okay; } } +} + +#[rustc_error] +pub fn main() { //~ ERROR compilation successful + let s = S; + s.m1(); + s.m2(); + foo(); +} diff --git a/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs b/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs new file mode 100644 index 0000000000000..bbdd0774ed936 --- /dev/null +++ b/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs @@ -0,0 +1,120 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue #21633: reject duplicate loop labels in function bodies. +// This is testing interaction between lifetime-params and labels. + +#![feature(rustc_attrs)] + +#![allow(dead_code, unused_variables)] + +fn foo() { + fn foo<'a>() { //~ NOTE shadowed lifetime `'a` declared here + 'a: loop { break 'a; } + //~^ WARN label name `'a` shadows a lifetime name that is already in scope + } + + struct Struct<'b, 'c> { _f: &'b i8, _g: &'c i8 } + enum Enum<'d, 'e> { A(&'d i8), B(&'e i8) } + + impl<'d, 'e> Struct<'d, 'e> { + fn meth_okay() { + 'a: loop { break 'a; } + 'b: loop { break 'b; } + 'c: loop { break 'c; } + } + } + + impl <'d, 'e> Enum<'d, 'e> { + fn meth_okay() { + 'a: loop { break 'a; } + 'b: loop { break 'b; } + 'c: loop { break 'c; } + } + } + + impl<'bad, 'c> Struct<'bad, 'c> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl<'b, 'bad> Struct<'b, 'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad2(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl<'b, 'c> Struct<'b, 'c> { + fn meth_bad3<'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + + fn meth_bad4<'a,'bad>(x: &'a i8, y: &'bad i8) { + //~^ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl <'bad, 'e> Enum<'bad, 'e> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + impl <'d, 'bad> Enum<'d, 'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad2(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + impl <'d, 'e> Enum<'d, 'e> { + fn meth_bad3<'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + + fn meth_bad4<'a,'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + + trait HasDefaultMethod1<'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_okay() { + 'c: loop { break 'c; } + } + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + trait HasDefaultMethod2<'a,'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + trait HasDefaultMethod3<'a,'b> { + fn meth_bad<'bad>(&self) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } +} + +#[rustc_error] +pub fn main() { //~ ERROR compilation successful + foo(); +} diff --git a/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs b/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs new file mode 100644 index 0000000000000..2344d251c9a69 --- /dev/null +++ b/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs @@ -0,0 +1,41 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +#![allow(dead_code, unused_variables)] + +// Issue #21633: reject duplicate loop labels in function bodies. +// +// Test rejection of lifetimes in *expressions* that shadow loop labels. + +fn foo() { + // Reusing lifetime `'a` in function item is okay. + fn foo<'a>(x: &'a i8) -> i8 { *x } + + // So is reusing `'a` in struct item + struct S1<'a> { x: &'a i8 } impl<'a> S1<'a> { fn m(&self) {} } + // and a method item + struct S2; impl S2 { fn m<'a>(&self) {} } + + let z = 3_i8; + + 'a: loop { //~ NOTE shadowed label `'a` declared here + let b = Box::new(|x: &i8| *x) as Box Fn(&'a i8) -> i8>; + //~^ WARN lifetime name `'a` shadows a label name that is already in scope + assert_eq!((*b)(&z), z); + break 'a; + } +} + +#[rustc_error] +pub fn main() { //~ ERROR compilation successful + foo(); +} diff --git a/src/test/compile-fail/shadowed-lifetime.rs b/src/test/compile-fail/shadowed-lifetime.rs index 110b1a0d90c22..8cbab5f830809 100644 --- a/src/test/compile-fail/shadowed-lifetime.rs +++ b/src/test/compile-fail/shadowed-lifetime.rs @@ -15,14 +15,14 @@ struct Foo<'a>(&'a isize); impl<'a> Foo<'a> { //~^ NOTE shadowed lifetime `'a` declared here fn shadow_in_method<'a>(&'a self) -> &'a isize { - //~^ ERROR lifetime name `'a` shadows another lifetime name that is already in scope + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope self.0 } fn shadow_in_type<'b>(&'b self) -> &'b isize { //~^ NOTE shadowed lifetime `'b` declared here let x: for<'b> fn(&'b isize) = panic!(); - //~^ ERROR lifetime name `'b` shadows another lifetime name that is already in scope + //~^ ERROR lifetime name `'b` shadows a lifetime name that is already in scope self.0 } diff --git a/src/test/debuginfo/issue13213.rs b/src/test/debuginfo/issue13213.rs index 13dc0c6d12007..67975d02b19f0 100644 --- a/src/test/debuginfo/issue13213.rs +++ b/src/test/debuginfo/issue13213.rs @@ -12,8 +12,6 @@ // aux-build:issue13213aux.rs -#![feature(old_io)] - extern crate issue13213aux; // compile-flags:-g diff --git a/src/test/run-make/archive-duplicate-names/Makefile b/src/test/run-make/archive-duplicate-names/Makefile new file mode 100644 index 0000000000000..72c2d389e2aac --- /dev/null +++ b/src/test/run-make/archive-duplicate-names/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +all: + mkdir $(TMPDIR)/a + mkdir $(TMPDIR)/b + $(CC) -c -o $(TMPDIR)/a/foo.o foo.c + $(CC) -c -o $(TMPDIR)/b/foo.o bar.c + ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(call RUN,bar) diff --git a/src/test/run-make/archive-duplicate-names/bar.c b/src/test/run-make/archive-duplicate-names/bar.c new file mode 100644 index 0000000000000..a25fa10f4d3ee --- /dev/null +++ b/src/test/run-make/archive-duplicate-names/bar.c @@ -0,0 +1,11 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +void bar() {} diff --git a/src/test/run-make/archive-duplicate-names/bar.rs b/src/test/run-make/archive-duplicate-names/bar.rs new file mode 100644 index 0000000000000..1200a6de8e2e0 --- /dev/null +++ b/src/test/run-make/archive-duplicate-names/bar.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate foo; + +fn main() { + foo::baz(); +} diff --git a/src/test/run-make/archive-duplicate-names/foo.c b/src/test/run-make/archive-duplicate-names/foo.c new file mode 100644 index 0000000000000..61d5d15407891 --- /dev/null +++ b/src/test/run-make/archive-duplicate-names/foo.c @@ -0,0 +1,11 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +void foo() {} diff --git a/src/test/run-make/archive-duplicate-names/foo.rs b/src/test/run-make/archive-duplicate-names/foo.rs new file mode 100644 index 0000000000000..24b4734f2cd33 --- /dev/null +++ b/src/test/run-make/archive-duplicate-names/foo.rs @@ -0,0 +1,24 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +#[link(name = "foo", kind = "static")] +extern { + fn foo(); + fn bar(); +} + +pub fn baz() { + unsafe { + foo(); + bar(); + } +} diff --git a/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs b/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs index 02af5244b8aab..fd69d2786b8d0 100644 --- a/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs +++ b/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(old_io, old_path)] - use std::env; use std::fs::File; use std::process::Command; diff --git a/src/test/run-make/extern-fn-reachable/main.rs b/src/test/run-make/extern-fn-reachable/main.rs index b93bdbaa16f2a..244f32b8ee5fc 100644 --- a/src/test/run-make/extern-fn-reachable/main.rs +++ b/src/test/run-make/extern-fn-reachable/main.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(std_misc, old_path, os)] +#![feature(std_misc)] use std::dynamic_lib::DynamicLibrary; -use std::os; use std::path::Path; pub fn main() { diff --git a/src/test/run-pass/closure-reform.rs b/src/test/run-pass/closure-reform.rs index 50f05c050b173..0fa67e873f89c 100644 --- a/src/test/run-pass/closure-reform.rs +++ b/src/test/run-pass/closure-reform.rs @@ -11,9 +11,7 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ -#![feature(unboxed_closures, old_io)] - -use std::mem; +#![feature(unboxed_closures)] fn call_it(f: F) where F : FnOnce(String) -> String diff --git a/src/test/run-pass/drop-with-type-ascription-1.rs b/src/test/run-pass/drop-with-type-ascription-1.rs index 9dd458344cb5a..15f229dbca5d9 100644 --- a/src/test/run-pass/drop-with-type-ascription-1.rs +++ b/src/test/run-pass/drop-with-type-ascription-1.rs @@ -9,11 +9,9 @@ // except according to those terms. -#![feature(str_words)] - fn main() { let foo = "hello".to_string(); - let foo: Vec<&str> = foo.words().collect(); + let foo: Vec<&str> = foo.split_whitespace().collect(); let invalid_string = &foo[0]; assert_eq!(*invalid_string, "hello"); } diff --git a/src/test/run-pass/hygienic-labels-in-let.rs b/src/test/run-pass/hygienic-labels-in-let.rs index 589d6e1581bde..5b45f1e0d3928 100644 --- a/src/test/run-pass/hygienic-labels-in-let.rs +++ b/src/test/run-pass/hygienic-labels-in-let.rs @@ -10,6 +10,14 @@ // ignore-pretty: pprust doesn't print hygiene output +// Test that labels injected by macros do not break hygiene. This +// checks cases where the macros invocations are under the rhs of a +// let statement. + +// Issue #24278: The label/lifetime shadowing checker from #24162 +// conservatively ignores hygiene, and thus issues warnings that are +// both true- and false-positives for this test. + macro_rules! loop_x { ($e: expr) => { // $e shouldn't be able to interact with this 'x diff --git a/src/test/run-pass/hygienic-labels.rs b/src/test/run-pass/hygienic-labels.rs index df72a5410a2b2..a5882f022920f 100644 --- a/src/test/run-pass/hygienic-labels.rs +++ b/src/test/run-pass/hygienic-labels.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test that labels injected by macros do not break hygiene. + +// Issue #24278: The label/lifetime shadowing checker from #24162 +// conservatively ignores hygiene, and thus issues warnings that are +// both true- and false-positives for this test. macro_rules! loop_x { ($e: expr) => { diff --git a/src/test/run-pass/issue-10626.rs b/src/test/run-pass/issue-10626.rs index 0d8f22254857d..c81e16ebb7c60 100644 --- a/src/test/run-pass/issue-10626.rs +++ b/src/test/run-pass/issue-10626.rs @@ -12,8 +12,6 @@ // Make sure that if a process doesn't have its stdio/stderr descriptors set up // that we don't die in a large ball of fire -#![feature(old_io)] - use std::env; use std::process::{Command, Stdio}; diff --git a/src/test/run-pass/issue-11881.rs b/src/test/run-pass/issue-11881.rs index 483ae02d2dcbd..9da04f7235531 100644 --- a/src/test/run-pass/issue-11881.rs +++ b/src/test/run-pass/issue-11881.rs @@ -9,7 +9,7 @@ // except according to those terms. -#![feature(rustc_private, old_io)] +#![feature(rustc_private)] extern crate rbml; extern crate serialize; diff --git a/src/test/run-pass/issue-14940.rs b/src/test/run-pass/issue-14940.rs index b51afc1d02095..ba6815d5b7c69 100644 --- a/src/test/run-pass/issue-14940.rs +++ b/src/test/run-pass/issue-14940.rs @@ -9,8 +9,6 @@ // except according to those terms. -#![feature(old_io, io)] - use std::env; use std::process::Command; use std::io::{self, Write}; diff --git a/src/test/run-pass/issue-21245.rs b/src/test/run-pass/issue-21245.rs index 75d064a00fa89..e3340d9767d02 100644 --- a/src/test/run-pass/issue-21245.rs +++ b/src/test/run-pass/issue-21245.rs @@ -20,19 +20,19 @@ use std::ptr; trait IntoIterator { type Iter: Iterator; - fn into_iter(self) -> Self::Iter; + fn into_iter2(self) -> Self::Iter; } impl IntoIterator for I where I: Iterator { type Iter = I; - fn into_iter(self) -> I { + fn into_iter2(self) -> I { self } } fn desugared_for_loop_bad(v: Vec) { - match IntoIterator::into_iter(v.iter()) { + match IntoIterator::into_iter2(v.iter()) { mut iter => { loop { match ::std::iter::Iterator::next(&mut iter) { diff --git a/src/test/run-pass/linkage-visibility.rs b/src/test/run-pass/linkage-visibility.rs index 945cf9370f414..74da4273b6ab0 100644 --- a/src/test/run-pass/linkage-visibility.rs +++ b/src/test/run-pass/linkage-visibility.rs @@ -12,7 +12,7 @@ // ignore-android: FIXME(#10379) // ignore-windows: std::dynamic_lib does not work on Windows well -#![feature(std_misc, old_path)] +#![feature(std_misc)] extern crate linkage_visibility as foo; diff --git a/src/test/run-pass/logging-separate-lines.rs b/src/test/run-pass/logging-separate-lines.rs index 29cfe91eba5ac..09759326afd91 100644 --- a/src/test/run-pass/logging-separate-lines.rs +++ b/src/test/run-pass/logging-separate-lines.rs @@ -12,7 +12,7 @@ // exec-env:RUST_LOG=debug // compile-flags:-C debug-assertions=y -#![feature(old_io, rustc_private)] +#![feature(rustc_private)] #[macro_use] extern crate log; diff --git a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs index 1611a2c07227a..5eecf27db677b 100644 --- a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs +++ b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs @@ -13,9 +13,8 @@ // temporary. Issue #19147. -#![feature(core, old_io)] +#![feature(core)] -use std::mem; use std::slice; pub type IoResult = Result; diff --git a/src/test/run-pass/process-spawn-with-unicode-params.rs b/src/test/run-pass/process-spawn-with-unicode-params.rs index 32448d100fb9b..a155ee396b614 100644 --- a/src/test/run-pass/process-spawn-with-unicode-params.rs +++ b/src/test/run-pass/process-spawn-with-unicode-params.rs @@ -17,15 +17,13 @@ // intact. // ignore-aarch64 -#![feature(path, fs, os, io, old_path)] use std::io::prelude::*; use std::io; use std::fs; use std::process::Command; -use std::os; use std::env; -use std::path::{Path, PathBuf}; +use std::path::Path; fn main() { let my_args = env::args().collect::>(); diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs index 31d97305e0be4..db543116d17a5 100644 --- a/src/test/run-pass/running-with-no-runtime.rs +++ b/src/test/run-pass/running-with-no-runtime.rs @@ -8,16 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(start, os, std_misc, old_io)] +#![feature(start, std_misc)] use std::ffi::CStr; use std::process::{Command, Output}; -use std::os; use std::rt::unwind::try; -use std::rt; use std::str; -use std::thread::Thread; -use std::thunk::Thunk; #[start] fn start(argc: isize, argv: *const *const u8) -> isize { diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs index 7bcde7b83cd1b..4a1bb5a5916f0 100644 --- a/src/test/run-pass/task-stderr.rs +++ b/src/test/run-pass/task-stderr.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// pretty-expanded FIXME #23616 - -#![allow(unknown_features)] -#![feature(box_syntax, old_io, std_misc, io, set_panic, set_stdio)] +#![feature(box_syntax, set_stdio)] use std::io::prelude::*; use std::io; diff --git a/src/test/run-pass/trait-coercion.rs b/src/test/run-pass/trait-coercion.rs index fa31d9891aaf7..d40d9c89f89df 100644 --- a/src/test/run-pass/trait-coercion.rs +++ b/src/test/run-pass/trait-coercion.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax, old_io, io)] +#![feature(box_syntax)] use std::io::{self, Write};