Just a small typo noticed while reading through documentation.
if [ ! -z "$CFG_ENABLE_LOCAL_RUST" ]
then
- if [ ! -f ${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF} ]
+ system_rustc=$(which rustc)
+ if [ -f ${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF} ]
then
- err "no local rust to use"
+ : # everything already configured
+ elif [ -n "$system_rustc" ]
+ then
+ # we assume that rustc is in a /bin directory
+ CFG_LOCAL_RUST_ROOT=${system_rustc%/bin/rustc}
else
- LRV=`${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF} --version`
- step_msg "using rustc at: ${CFG_LOCAL_RUST_ROOT} with version: $LRV"
+ err "no local rust to use"
fi
+
+ LRV=`${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF} --version`
+ step_msg "using rustc at: ${CFG_LOCAL_RUST_ROOT} with version: $LRV"
+ putvar CFG_LOCAL_RUST_ROOT
fi
# Force freebsd to build with clang; gcc doesn't like us there
possible and even pleasant, but it should not be a requirement for
implementing the language.
-## Non-`Share` `static mut` is unsafe
+## Non-`Sync` `static mut` is unsafe
-Types which are [`Share`][share] are thread-safe when multiple shared
-references to them are used concurrently. Types which are not `Share` are not
+Types which are [`Sync`][sync] are thread-safe when multiple shared
+references to them are used concurrently. Types which are not `Sync` are not
thread-safe, and thus when used in a global require unsafe code to use.
-[share]: http://doc.rust-lang.org/core/kinds/trait.Share.html
+[sync]: http://doc.rust-lang.org/core/kinds/trait.Sync.html
-### If mutable static items that implement `Share` are safe, why is taking &mut SHARABLE unsafe?
+### If mutable static items that implement `Sync` are safe, why is taking &mut SHARABLE unsafe?
Having multiple aliasing `&mut T`s is never allowed. Due to the nature of
globals, the borrow checker cannot possibly ensure that a static obeys the
- stack unwinding and general failure; the `eh_personality`, `fail_`
and `fail_bounds_checks` lang items.
- the traits in `std::kinds` used to indicate types that satisfy
- various kinds; lang items `send`, `share` and `copy`.
+ various kinds; lang items `send`, `sync` and `copy`.
- the marker types and variance indicators found in
`std::kinds::markers`; lang items `covariant_type`,
- `contravariant_lifetime`, `no_share_bound`, etc.
+ `contravariant_lifetime`, `no_sync_bound`, etc.
Lang items are loaded lazily by the compiler; e.g. if one never uses
`Box` then there is no need to define functions for `exchange_malloc`
# Patterns
-# Lambdas
+# Closures
+
+So far, we've made lots of functions in Rust. But we've given them all names.
+Rust also allows us to create anonymous functions too. Rust's anonymous
+functions are called **closure**s. By themselves, closures aren't all that
+interesting, but when you combine them with functions that take closures as
+arguments, really powerful things are possible.
+
+Let's make a closure:
+
+```{rust}
+let add_one = |x| { 1i + x };
+
+println!("The 5 plus 1 is {}.", add_one(5i));
+```
+
+We create a closure using the `|...| { ... }` syntax, and then we create a
+binding so we can use it later. Note that we call the function using the
+binding name and two parentheses, just like we would for a named function.
+
+Let's compare syntax. The two are pretty close:
+
+```{rust}
+let add_one = |x: int| -> int { 1i + x };
+fn add_one (x: int) -> int { 1i + x }
+```
+
+As you may have noticed, closures infer their argument and return types, so you
+don't need to declare one. This is different from named functions, which
+default to returning unit (`()`).
+
+There's one big difference between a closure and named functions, and it's in
+the name: a function "closes over its environment." What's that mean? It means
+this:
+
+```{rust}
+fn main() {
+ let x = 5i;
+
+ let printer = || { println!("x is: {}", x); };
+
+ printer(); // prints "x is: 5"
+}
+```
+
+The `||` syntax means this is an anonymous closure that takes no arguments.
+Without it, we'd just have a block of code in `{}`s.
+
+In other words, a closure has access to variables in the scope that it's
+defined. The closure borrows any variables that it uses. This will error:
+
+```{rust,ignore}
+fn main() {
+ let mut x = 5i;
+
+ let printer = || { println!("x is: {}", x); };
+
+ x = 6i; // error: cannot assign to `x` because it is borrowed
+}
+```
+
+## Procs
+
+Rust has a second type of closure, called a **proc**. Procs are created
+with the `proc` keyword:
+
+```{rust}
+let x = 5i;
+
+let p = proc() { x * x };
+println!("{}", p()); // prints 25
+```
+
+Procs have a big difference from closures: they may only be called once. This
+will error when we try to compile:
+
+```{rust,ignore}
+let x = 5i;
+
+let p = proc() { x * x };
+println!("{}", p());
+println!("{}", p()); // error: use of moved value `p`
+```
+
+This restriction is important. Procs are allowed to consume values that they
+capture, and thus have to be restricted to being called once for soundness
+reasons: any value consumed would be invalid on a second call.
+
+Procs are most useful with Rust's concurrency features, and so we'll just leave
+it at this for now. We'll talk about them more in the "Tasks" section of the
+guide.
+
+## Accepting closures as arguments
+
+Closures are most useful as an argument to another function. Here's an example:
+
+```{rust}
+fn twice(x: int, f: |int| -> int) -> int {
+ f(x) + f(x)
+}
+
+fn main() {
+ let square = |x: int| { x * x };
+
+ twice(5i, square); // evaluates to 50
+}
+```
+
+Let's break example down, starting with `main`:
+
+```{rust}
+let square = |x: int| { x * x };
+```
+
+We've seen this before. We make a closure that takes an integer, and returns
+its square.
+
+```{rust,ignore}
+twice(5i, square); // evaluates to 50
+```
+
+This line is more interesting. Here, we call our function, `twice`, and we pass
+it two arguments: an integer, `5`, and our closure, `square`. This is just like
+passing any other two variable bindings to a function, but if you've never
+worked with closures before, it can seem a little complex. Just think: "I'm
+passing two variables, one is an int, and one is a function."
+
+Next, let's look at how `twice` is defined:
+
+```{rust,ignore}
+fn twice(x: int, f: |int| -> int) -> int {
+```
+
+`twice` takes two arguments, `x` and `f`. That's why we called it with two
+arguments. `x` is an `int`, we've done that a ton of times. `f` is a function,
+though, and that function takes an `int` and returns an `int`. Notice
+how the `|int| -> int` syntax looks a lot like our definition of `square`
+above, if we added the return type in:
+
+```{rust}
+let square = |x: int| -> int { x * x };
+// |int| -> int
+```
+
+This function takes an `int` and returns an `int`.
+
+This is the most complicated function signature we've seen yet! Give it a read
+a few times until you can see how it works. It takes a teeny bit of practice, and
+then it's easy.
+
+Finally, `twice` returns an `int` as well.
+
+Okay, let's look at the body of `twice`:
+
+```{rust}
+fn twice(x: int, f: |int| -> int) -> int {
+ f(x) + f(x)
+}
+```
+
+Since our closure is named `f`, we can call it just like we called our closures
+before. And we pass in our `x` argument to each one. Hence 'twice.'
+
+If you do the math, `(5 * 5) + (5 * 5) == 50`, so that's the output we get.
+
+Play around with this concept until you're comfortable with it. Rust's standard
+library uses lots of closures, where appropriate, so you'll be using
+this technique a lot.
+
+If we didn't want to give `square` a name, we could also just define it inline.
+This example is the same as the previous one:
+
+```{rust}
+fn twice(x: int, f: |int| -> int) -> int {
+ f(x) + f(x)
+}
+
+fn main() {
+ twice(5i, |x: int| { x * x }); // evaluates to 50
+}
+```
+
+A named function's name can be used wherever you'd use a closure. Another
+way of writing the previous example:
+
+```{rust}
+fn twice(x: int, f: |int| -> int) -> int {
+ f(x) + f(x)
+}
+
+fn square(x: int) -> int { x * x }
+
+fn main() {
+ twice(5i, square); // evaluates to 50
+}
+```
+
+Doing this is not particularly common, but every once in a while, it's useful.
+
+That's all you need to get the hang of closures! Closures are a little bit
+strange at first, but once you're used to using them, you'll miss them in any
+language that doesn't have them. Passing functions to other functions is
+incredibly powerful. Next, let's look at one of those things: iterators.
# iterators
# Generics
+Sometimes, when writing a function or data type, we may want it to work for
+multiple types of arguments. For example, remember our `OptionalInt` type?
+
+```{rust}
+enum OptionalInt {
+ Value(int),
+ Missing,
+}
+```
+
+If we wanted to also have an `OptionalFloat64`, we would need a new enum:
+
+```{rust}
+enum OptionalFloat64 {
+ Valuef64(f64),
+ Missingf64,
+}
+```
+
+This is really unfortunate. Luckily, Rust has a feature that gives us a better
+way: generics. Generics are called **parametric polymorphism** in type theory,
+which means that they are types or functions that have multiple forms ("poly"
+is multiple, "morph" is form) over a given parameter ("parametric").
+
+Anyway, enough with type theory declarations, let's check out the generic form
+of `OptionalInt`. It is actually provided by Rust itself, and looks like this:
+
+```rust
+enum Option<T> {
+ Some(T),
+ None,
+}
+```
+
+The `<T>` part, which you've seen a few times before, indicates that this is
+a generic data type. Inside the declaration of our enum, wherever we see a `T`,
+we substitute that type for the same type used in the generic. Here's an
+example of using `Option<T>`, with some extra type annotations:
+
+```{rust}
+let x: Option<int> = Some(5i);
+```
+
+In the type declaration, we say `Option<int>`. Note how similar this looks to
+`Option<T>`. So, in this particular `Option`, `T` has the value of `int`. On
+the right hand side of the binding, we do make a `Some(T)`, where `T` is `5i`.
+Since that's an `int`, the two sides match, and Rust is happy. If they didn't
+match, we'd get an error:
+
+```{rust,ignore}
+let x: Option<f64> = Some(5i);
+// error: mismatched types: expected `core::option::Option<f64>`
+// but found `core::option::Option<int>` (expected f64 but found int)
+```
+
+That doesn't mean we can't make `Option<T>`s that hold an `f64`! They just have to
+match up:
+
+```{rust}
+let x: Option<int> = Some(5i);
+let y: Option<f64> = Some(5.0f64);
+```
+
+This is just fine. One definition, multiple uses.
+
+Generics don't have to only be generic over one type. Consider Rust's built-in
+`Result<T, E>` type:
+
+```{rust}
+enum Result<T, E> {
+ Ok(T),
+ Err(E),
+}
+```
+
+This type is generic over _two_ types: `T` and `E`. By the way, the capital letters
+can be any letter you'd like. We could define `Result<T, E>` as:
+
+```{rust}
+enum Result<H, N> {
+ Ok(H),
+ Err(N),
+}
+```
+
+if we wanted to. Convention says that the first generic parameter should be
+`T`, for 'type,' and that we use `E` for 'error.' Rust doesn't care, however.
+
+The `Result<T, E>` type is intended to
+be used to return the result of a computation, and to have the ability to
+return an error if it didn't work out. Here's an example:
+
+```{rust}
+let x: Result<f64, String> = Ok(2.3f64);
+let y: Result<f64, String> = Err("There was an error.".to_string());
+```
+
+This particular Result will return an `f64` if there's a success, and a
+`String` if there's a failure. Let's write a function that uses `Result<T, E>`:
+
+```{rust}
+fn inverse(x: f64) -> Result<f64, String> {
+ if x == 0.0f64 { return Err("x cannot be zero!".to_string()); }
+
+ Ok(1.0f64 / x)
+}
+```
+
+We don't want to take the inverse of zero, so we check to make sure that we
+weren't passed one. If we weren't, then we return an `Err`, with a message. If
+it's okay, we return an `Ok`, with the answer.
+
+Why does this matter? Well, remember how `match` does exhaustive matches?
+Here's how this function gets used:
+
+```{rust}
+# fn inverse(x: f64) -> Result<f64, String> {
+# if x == 0.0f64 { return Err("x cannot be zero!".to_string()); }
+# Ok(1.0f64 / x)
+# }
+let x = inverse(25.0f64);
+
+match x {
+ Ok(x) => println!("The inverse of 25 is {}", x),
+ Err(msg) => println!("Error: {}", msg),
+}
+```
+
+The `match` enforces that we handle the `Err` case. In addition, because the
+answer is wrapped up in an `Ok`, we can't just use the result without doing
+the match:
+
+```{rust,ignore}
+let x = inverse(25.0f64);
+println!("{}", x + 2.0f64); // error: binary operation `+` cannot be applied
+ // to type `core::result::Result<f64,collections::string::String>`
+```
+
+This function is great, but there's one other problem: it only works for 64 bit
+floating point values. What if we wanted to handle 32 bit floating point as
+well? We'd have to write this:
+
+```{rust}
+fn inverse32(x: f32) -> Result<f32, String> {
+ if x == 0.0f32 { return Err("x cannot be zero!".to_string()); }
+
+ Ok(1.0f32 / x)
+}
+```
+
+Bummer. What we need is a **generic function**. Luckily, we can write one!
+However, it won't _quite_ work yet. Before we get into that, let's talk syntax.
+A generic version of `inverse` would look something like this:
+
+```{rust,ignore}
+fn inverse<T>(x: T) -> Result<T, String> {
+ if x == 0.0 { return Err("x cannot be zero!".to_string()); }
+
+ Ok(1.0 / x)
+}
+```
+
+Just like how we had `Option<T>`, we use a similar syntax for `inverse<T>`.
+We can then use `T` inside the rest of the signature: `x` has type `T`, and half
+of the `Result` has type `T`. However, if we try to compile that example, we'll get
+an error:
+
+```{notrust,ignore}
+error: binary operation `==` cannot be applied to type `T`
+```
+
+Because `T` can be _any_ type, it may be a type that doesn't implement `==`,
+and therefore, the first line would be wrong. What do we do?
+
+To fix this example, we need to learn about another Rust feature: traits.
+
# Traits
-# Operators and built-in Traits
+Do you remember the `impl` keyword, used to call a function with method
+syntax?
+
+```{rust}
+struct Circle {
+ x: f64,
+ y: f64,
+ radius: f64,
+}
+
+impl Circle {
+ fn area(&self) -> f64 {
+ std::f64::consts::PI * (self.radius * self.radius)
+ }
+}
+```
+
+Traits are similar, except that we define a trait with just the method
+signature, then implement the trait for that struct. Like this:
+
+```{rust}
+struct Circle {
+ x: f64,
+ y: f64,
+ radius: f64,
+}
+
+trait HasArea {
+ fn area(&self) -> f64;
+}
+
+impl HasArea for Circle {
+ fn area(&self) -> f64 {
+ std::f64::consts::PI * (self.radius * self.radius)
+ }
+}
+```
+
+As you can see, the `trait` block looks very similar to the `impl` block,
+but we don't define a body, just a type signature. When we `impl` a trait,
+we use `impl Trait for Item`, rather than just `impl Item`.
+
+So what's the big deal? Remember the error we were getting with our generic
+`inverse` function?
+
+```{notrust,ignore}
+error: binary operation `==` cannot be applied to type `T`
+```
+
+We can use traits to constrain our generics. Consider this function, which
+does not compile, and gives us a similar error:
+
+```{rust,ignore}
+fn print_area<T>(shape: T) {
+ println!("This shape has an area of {}", shape.area());
+}
+```
+
+Rust complains:
+
+```{notrust,ignore}
+error: type `T` does not implement any method in scope named `area`
+```
+
+Because `T` can be any type, we can't be sure that it implements the `area`
+method. But we can add a **trait constraint** to our generic `T`, ensuring
+that it does:
+
+```{rust}
+# trait HasArea {
+# fn area(&self) -> f64;
+# }
+fn print_area<T: HasArea>(shape: T) {
+ println!("This shape has an area of {}", shape.area());
+}
+```
+
+The syntax `<T: HasArea>` means `any type that implements the HasArea trait`.
+Because traits define function type signatures, we can be sure that any type
+which implements `HasArea` will have an `.area()` method.
+
+Here's an extended example of how this works:
+
+```{rust}
+trait HasArea {
+ fn area(&self) -> f64;
+}
+
+struct Circle {
+ x: f64,
+ y: f64,
+ radius: f64,
+}
+
+impl HasArea for Circle {
+ fn area(&self) -> f64 {
+ std::f64::consts::PI * (self.radius * self.radius)
+ }
+}
+
+struct Square {
+ x: f64,
+ y: f64,
+ side: f64,
+}
+
+impl HasArea for Square {
+ fn area(&self) -> f64 {
+ self.side * self.side
+ }
+}
+
+fn print_area<T: HasArea>(shape: T) {
+ println!("This shape has an area of {}", shape.area());
+}
+
+fn main() {
+ let c = Circle {
+ x: 0.0f64,
+ y: 0.0f64,
+ radius: 1.0f64,
+ };
+
+ let s = Square {
+ x: 0.0f64,
+ y: 0.0f64,
+ side: 1.0f64,
+ };
+
+ print_area(c);
+ print_area(s);
+}
+```
+
+This program outputs:
+
+```{notrust,ignore}
+This shape has an area of 3.141593
+This shape has an area of 1
+```
+
+As you can see, `print_area` is now generic, but also ensures that we
+have passed in the correct types. If we pass in an incorrect type:
+
+```{rust,ignore}
+print_area(5i);
+```
+
+We get a compile-time error:
+
+```{notrust,ignore}
+error: failed to find an implementation of trait main::HasArea for int
+```
+
+So far, we've only added trait implementations to structs, but you can
+implement a trait for any type. So technically, we _could_ implement
+`HasArea` for `int`:
+
+```{rust}
+trait HasArea {
+ fn area(&self) -> f64;
+}
+
+impl HasArea for int {
+ fn area(&self) -> f64 {
+ println!("this is silly");
+
+ *self as f64
+ }
+}
+
+5i.area();
+```
+
+It is considered poor style to implement methods on such primitive types, even
+though it is possible.
+
+This may seem like the Wild West, but there are two other restrictions around
+implementing traits that prevent this from getting out of hand. First, traits
+must be `use`d in any scope where you wish to use the trait's method. So for
+example, this does not work:
+
+```{rust,ignore}
+mod shapes {
+ use std::f64::consts;
+
+ trait HasArea {
+ fn area(&self) -> f64;
+ }
+
+ struct Circle {
+ x: f64,
+ y: f64,
+ radius: f64,
+ }
+
+ impl HasArea for Circle {
+ fn area(&self) -> f64 {
+ consts::PI * (self.radius * self.radius)
+ }
+ }
+}
+
+fn main() {
+ let c = shapes::Circle {
+ x: 0.0f64,
+ y: 0.0f64,
+ radius: 1.0f64,
+ };
+
+ println!("{}", c.area());
+}
+```
+
+Now that we've moved the structs and traits into their own module, we get an
+error:
+
+```{notrust,ignore}
+error: type `shapes::Circle` does not implement any method in scope named `area`
+```
+
+If we add a `use` line right above `main` and make the right things public,
+everything is fine:
+
+```{rust}
+use shapes::HasArea;
+
+mod shapes {
+ use std::f64::consts;
+
+ pub trait HasArea {
+ fn area(&self) -> f64;
+ }
+
+ pub struct Circle {
+ pub x: f64,
+ pub y: f64,
+ pub radius: f64,
+ }
+
+ impl HasArea for Circle {
+ fn area(&self) -> f64 {
+ consts::PI * (self.radius * self.radius)
+ }
+ }
+}
+
+
+fn main() {
+ let c = shapes::Circle {
+ x: 0.0f64,
+ y: 0.0f64,
+ radius: 1.0f64,
+ };
+
+ println!("{}", c.area());
+}
+```
+
+This means that even if someone does something bad like add methods to `int`,
+it won't affect you, unless you `use` that trait.
+
+There's one more restriction on implementing traits. Either the trait or the
+type you're writing the `impl` for must be inside your crate. So, we could
+implement the `HasArea` type for `int`, because `HasArea` is in our crate. But
+if we tried to implement `Float`, a trait provided by Rust, for `int`, we could
+not, because both the trait and the type aren't in our crate.
+
+One last thing about traits: generic functions with a trait bound use
+**monomorphization** ("mono": one, "morph": form), so they are statically
+dispatched. What's that mean? Well, let's take a look at `print_area` again:
+
+```{rust,ignore}
+fn print_area<T: HasArea>(shape: T) {
+ println!("This shape has an area of {}", shape.area());
+}
+
+fn main() {
+ let c = Circle { ... };
+
+ let s = Square { ... };
+
+ print_area(c);
+ print_area(s);
+}
+```
+
+When we use this trait with `Circle` and `Square`, Rust ends up generating
+two different functions with the concrete type, and replacing the call sites with
+calls to the concrete implementations. In other words, you get something like
+this:
+
+```{rust,ignore}
+fn __print_area_circle(shape: Circle) {
+ println!("This shape has an area of {}", shape.area());
+}
+
+fn __print_area_square(shape: Square) {
+ println!("This shape has an area of {}", shape.area());
+}
+
+fn main() {
+ let c = Circle { ... };
+
+ let s = Square { ... };
+
+ __print_area_circle(c);
+ __print_area_square(s);
+}
+```
+
+The names don't actually change to this, it's just for illustration. But
+as you can see, there's no overhead of deciding which version to call here,
+hence 'statically dispatched.' The downside is that we have two copies of
+the same function, so our binary is a little bit larger.
# Tasks
+Concurrency and parallelism are topics that are of increasing interest to a
+broad subsection of software developers. Modern computers are often multi-core,
+to the point that even embedded devices like cell phones have more than one
+processor. Rust's semantics lend themselves very nicely to solving a number of
+issues that programmers have with concurrency. Many concurrency errors that are
+runtime errors in other languages are compile-time errors in Rust.
+
+Rust's concurrency primitive is called a **task**. Tasks are lightweight, and
+do not share memory in an unsafe manner, preferring message passing to
+communicate. It's worth noting that tasks are implemented as a library, and
+not part of the language. This means that in the future, other concurrency
+libraries can be written for Rust to help in specific scenarios. Here's an
+example of creating a task:
+
+```{rust}
+spawn(proc() {
+ println!("Hello from a task!");
+});
+```
+
+The `spawn` function takes a proc as an argument, and runs that proc in a new
+task. A proc takes ownership of its entire environment, and so any variables
+that you use inside the proc will not be usable afterward:
+
+```{rust,ignore}
+let mut x = vec![1i, 2i, 3i];
+
+spawn(proc() {
+ println!("The value of x[0] is: {}", x[0]);
+});
+
+println!("The value of x[0] is: {}", x[0]); // error: use of moved value: `x`
+```
+
+`x` is now owned by the proc, and so we can't use it anymore. Many other
+languages would let us do this, but it's not safe to do so. Rust's type system
+catches the error.
+
+If tasks were only able to capture these values, they wouldn't be very useful.
+Luckily, tasks can communicate with each other through **channel**s. Channels
+work like this:
+
+```{rust}
+let (tx, rx) = channel();
+
+spawn(proc() {
+ tx.send("Hello from a task!".to_string());
+});
+
+let message = rx.recv();
+println!("{}", message);
+```
+
+The `channel()` function returns two endpoints: a `Receiver<T>` and a
+`Sender<T>`. You can use the `.send()` method on the `Sender<T>` end, and
+receive the message on the `Receiver<T>` side with the `recv()` method. This
+method blocks until it gets a message. There's a similar method, `.try_recv()`,
+which returns an `Option<T>` and does not block.
+
+If you want to send messages to the task as well, create two channels!
+
+```{rust}
+let (tx1, rx1) = channel();
+let (tx2, rx2) = channel();
+
+spawn(proc() {
+ tx1.send("Hello from a task!".to_string());
+ let message = rx2.recv();
+ println!("{}", message);
+});
+
+let message = rx1.recv();
+println!("{}", message);
+
+tx2.send("Goodbye from main!".to_string());
+```
+
+The proc has one sending end and one receiving end, and the main task has one
+of each as well. Now they can talk back and forth in whatever way they wish.
+
+Notice as well that because `Sender` and `Receiver` are generic, while you can
+pass any kind of information through the channel, the ends are strongly typed.
+If you try to pass a string, and then an integer, Rust will complain.
+
+## Futures
+
+With these basic primitives, many different concurrency patterns can be
+developed. Rust includes some of these types in its standard library. For
+example, if you wish to compute some value in the background, `Future` is
+a useful thing to use:
+
+```{rust}
+use std::sync::Future;
+
+let mut delayed_value = Future::spawn(proc() {
+ // just return anything for examples' sake
+
+ 12345i
+});
+println!("value = {}", delayed_value.get());
+```
+
+Calling `Future::spawn` works just like `spawn()`: it takes a proc. In this
+case, though, you don't need to mess with the channel: just have the proc
+return the value.
+
+`Future::spawn` will return a value which we can bind with `let`. It needs
+to be mutable, because once the value is computed, it saves a copy of the
+value, and if it were immutable, it couldn't update itself.
+
+The proc will go on processing in the background, and when we need the final
+value, we can call `get()` on it. This will block until the result is done,
+but if it's finished computing in the background, we'll just get the value
+immediately.
+
+## Success and failure
+
+Tasks don't always succeed, they can also fail. A task that wishes to fail
+can call the `fail!` macro, passing a message:
+
+```{rust}
+spawn(proc() {
+ fail!("Nope.");
+});
+```
+
+If a task fails, it is not possible for it to recover. However, it can
+notify other tasks that it has failed. We can do this with `task::try`:
+
+```{rust}
+use std::task;
+use std::rand;
+
+let result = task::try(proc() {
+ if rand::random() {
+ println!("OK");
+ } else {
+ fail!("oops!");
+ }
+});
+```
+
+This task will randomly fail or succeed. `task::try` returns a `Result`
+type, so we can handle the response like any other computation that may
+fail.
+
# Macros
# Unsafe
: Has a size known at compile time.
* `copy`
: Types that do not move ownership when used by-value.
-* `share`
+* `sync`
: Able to be safely shared between tasks when aliased.
* `drop`
: Have destructors.
: This type does not implement "send", even if eligible
* `no_copy_bound`
: This type does not implement "copy", even if eligible
-* `no_share_bound`
- : This type does not implement "share", even if eligible
+* `no_sync_bound`
+ : This type does not implement "sync", even if eligible
* `managed_bound`
: This type implements "managed"
> the precise details of which are not discussed here.
For Linux and OS X, the install page provides links to binary tarballs.
-To install the Rust compiler from the from a binary tarball, download
+To install the Rust compiler from a binary tarball, download
the binary package, extract it, and execute the `install.sh` script in
the root directory of the package.
Types are sendable
unless they contain references.
-* `Share` - Types that are *threadsafe*.
+* `Sync` - Types that are *threadsafe*.
These are types that are safe to be used across several threads with access to
a `&T` pointer. `Mutex<T>` is an example of a *sharable* type with internal mutable data.
given signature. This means that we can call `print` on an argument
of any type that implements the `Printable` trait.
-Rust's built-in `Send` and `Share` types are examples of traits that
+Rust's built-in `Send` and `Sync` types are examples of traits that
don't provide any methods.
Traits may be implemented for specific types with [impls]. An impl for
This usage of traits is similar to Java interfaces.
-There are some built-in bounds, such as `Send` and `Share`, which are properties
+There are some built-in bounds, such as `Send` and `Sync`, which are properties
of the components of types. By design, trait objects don't know the exact type
of their contents and so the compiler cannot reason about those properties.
trait Bar<T> {}
fn sendable_foo(f: Box<Foo + Send>) { /* ... */ }
-fn shareable_bar<T: Share>(b: &Bar<T> + Share) { /* ... */ }
+fn sync_bar<T: Sync>(b: &Bar<T> + Sync) { /* ... */ }
~~~
When no colon is specified (such as the type `Box<Foo>`), it is inferred that the
" to make it easy to update.
" Core operators {{{3
-syn keyword rustTrait Copy Send Sized Share
+syn keyword rustTrait Copy Send Sized Sync
syn keyword rustTrait Add Sub Mul Div Rem Neg Not
syn keyword rustTrait BitAnd BitOr BitXor
syn keyword rustTrait Drop Deref DerefMut
use core::atomic;
use core::clone::Clone;
-use core::kinds::{Share, Send};
+use core::kinds::{Sync, Send};
use core::mem::{min_align_of, size_of, drop};
use core::mem;
use core::ops::{Drop, Deref};
data: T,
}
-impl<T: Share + Send> Arc<T> {
+impl<T: Sync + Send> Arc<T> {
/// Create an atomically reference counted wrapper.
#[inline]
#[stable]
fn inner(&self) -> &ArcInner<T> {
// This unsafety is ok because while this arc is alive we're guaranteed
// that the inner pointer is valid. Furthermore, we know that the
- // `ArcInner` structure itself is `Share` because the inner data is
- // `Share` as well, so we're ok loaning out an immutable pointer to
+ // `ArcInner` structure itself is `Sync` because the inner data is
+ // `Sync` as well, so we're ok loaning out an immutable pointer to
// these contents.
unsafe { &*self._ptr }
}
}
#[unstable = "waiting on stability of Clone"]
-impl<T: Share + Send> Clone for Arc<T> {
+impl<T: Sync + Send> Clone for Arc<T> {
/// Duplicate an atomically reference counted wrapper.
///
/// The resulting two `Arc` objects will point to the same underlying data
}
#[experimental = "Deref is experimental."]
-impl<T: Send + Share> Deref<T> for Arc<T> {
+impl<T: Send + Sync> Deref<T> for Arc<T> {
#[inline]
fn deref(&self) -> &T {
&self.inner().data
}
}
-impl<T: Send + Share + Clone> Arc<T> {
+impl<T: Send + Sync + Clone> Arc<T> {
/// Acquires a mutable pointer to the inner contents by guaranteeing that
/// the reference count is one (no sharing is possible).
///
#[unsafe_destructor]
#[experimental = "waiting on stability of Drop"]
-impl<T: Share + Send> Drop for Arc<T> {
+impl<T: Sync + Send> Drop for Arc<T> {
fn drop(&mut self) {
// This structure has #[unsafe_no_drop_flag], so this drop glue may run
// more than once (but it is guaranteed to be zeroed after the first if
}
#[experimental = "Weak pointers may not belong in this module."]
-impl<T: Share + Send> Weak<T> {
+impl<T: Sync + Send> Weak<T> {
/// Attempts to upgrade this weak reference to a strong reference.
///
/// This method will fail to upgrade this reference if the strong reference
}
#[experimental = "Weak pointers may not belong in this module."]
-impl<T: Share + Send> Clone for Weak<T> {
+impl<T: Sync + Send> Clone for Weak<T> {
#[inline]
fn clone(&self) -> Weak<T> {
// See comments in Arc::clone() for why this is relaxed
#[unsafe_destructor]
#[experimental = "Weak pointers may not belong in this module."]
-impl<T: Share + Send> Drop for Weak<T> {
+impl<T: Sync + Send> Drop for Weak<T> {
fn drop(&mut self) {
// see comments above for why this check is here
if self._ptr.is_null() { return }
// field accesses of the contained type via Deref
_ptr: *mut RcBox<T>,
_nosend: marker::NoSend,
- _noshare: marker::NoShare
+ _noshare: marker::NoSync
}
#[stable]
weak: Cell::new(1)
}),
_nosend: marker::NoSend,
- _noshare: marker::NoShare
+ _noshare: marker::NoSync
}
}
}
Weak {
_ptr: self._ptr,
_nosend: marker::NoSend,
- _noshare: marker::NoShare
+ _noshare: marker::NoSync
}
}
}
#[inline]
fn clone(&self) -> Rc<T> {
self.inc_strong();
- Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoShare }
+ Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
}
}
// field accesses of the contained type via Deref
_ptr: *mut RcBox<T>,
_nosend: marker::NoSend,
- _noshare: marker::NoShare
+ _noshare: marker::NoSync
}
#[experimental = "Weak pointers may not belong in this module."]
None
} else {
self.inc_strong();
- Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoShare })
+ Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync })
}
}
}
#[inline]
fn clone(&self) -> Weak<T> {
self.inc_weak();
- Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoShare }
+ Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
}
}
/*!
-Utilities for vector manipulation
+Utilities for slice manipulation
-The `vec` module contains useful code to help work with vector values.
-Vectors are Rust's list type. Vectors contain zero or more values of
-homogeneous types:
+The `slice` module contains useful code to help work with slice values.
+Slices are a view into a block of memory represented as a pointer and a length.
```rust
-let int_vector = [1i, 2i, 3i];
-let str_vector = ["one", "two", "three"];
+// slicing a Vec
+let vec = vec!(1i, 2, 3);
+let int_slice = vec.as_slice();
+// coercing an array to a slice
+let str_slice: &[&str] = ["one", "two", "three"];
```
-This is a big module, but for a high-level overview:
+Slices are either mutable or shared. The shared slice type is `&[T]`,
+while the mutable slice type is `&mut[T]`. For example, you can mutate the
+block of memory that a mutable slice points to:
+
+```rust
+let x: &mut[int] = [1i, 2, 3];
+x[1] = 7;
+assert_eq!(x[0], 1);
+assert_eq!(x[1], 7);
+assert_eq!(x[2], 3);
+```
+
+Here are some of the things this module contains:
## Structs
-Several structs that are useful for vectors, such as `Items`, which
-represents iteration over a vector.
+There are several structs that are useful for slices, such as `Items`, which
+represents iteration over a slice.
## Traits
-A number of traits add methods that allow you to accomplish tasks with vectors.
-
-Traits defined for the `&[T]` type (a vector slice), have methods that can be
-called on either owned vectors, denoted `~[T]`, or on vector slices themselves.
-These traits include `ImmutableVector`, and `MutableVector` for the `&mut [T]`
-case.
+A number of traits add methods that allow you to accomplish tasks with slices.
+These traits include `ImmutableVector`, which is defined for `&[T]` types,
+and `MutableVector`, defined for `&mut [T]` types.
An example is the method `.slice(a, b)` that returns an immutable "view" into
-a vector or a vector slice from the index interval `[a, b)`:
+a `Vec` or another slice from the index interval `[a, b)`:
```rust
let numbers = [0i, 1i, 2i];
// last_numbers is now &[1i, 2i]
```
-Traits defined for the `~[T]` type, like `OwnedVector`, can only be called
-on such vectors. These methods deal with adding elements or otherwise changing
-the allocation of the vector.
-
-An example is the method `.push(element)` that will add an element at the end
-of the vector:
-
-```rust
-let mut numbers = vec![0i, 1i, 2i];
-numbers.push(7);
-// numbers is now vec![0i, 1i, 2i, 7i];
-```
-
## Implementations of other traits
-Vectors are a very useful type, and so there's several implementations of
-traits from other modules. Some notable examples:
+There are several implementations of common traits for slices. Some examples
+include:
* `Clone`
-* `Eq`, `Ord`, `Eq`, `Ord` -- vectors can be compared,
- if the element type defines the corresponding trait.
+* `Eq`, `Ord` - for immutable slices whose element type are `Eq` or `Ord`.
+* `Hash` - for slices whose element type is `Hash`
## Iteration
-The method `iter()` returns an iteration value for a vector or a vector slice.
-The iterator yields references to the vector's elements, so if the element
-type of the vector is `int`, the element type of the iterator is `&int`.
+The method `iter()` returns an iteration value for a slice. The iterator
+yields references to the slice's elements, so if the element
+type of the slice is `int`, the element type of the iterator is `&int`.
```rust
let numbers = [0i, 1i, 2i];
```
* `.mut_iter()` returns an iterator that allows modifying each value.
-* `.move_iter()` converts an owned vector into an iterator that
- moves out a value from the vector each iteration.
-* Further iterators exist that split, chunk or permute the vector.
-
-## Function definitions
-
-There are a number of free functions that create or take vectors, for example:
-
-* Creating a vector, like `from_elem` and `from_fn`
-* Creating a vector with a given size: `with_capacity`
-* Modifying a vector and returning it, like `append`
-* Operations on paired elements, like `unzip`.
+* Further iterators exist that split, chunk or permute the slice.
*/
#[unstable = "likely to be renamed; otherwise stable"]
pub struct Cell<T> {
value: UnsafeCell<T>,
- noshare: marker::NoShare,
+ noshare: marker::NoSync,
}
#[stable]
pub fn new(value: T) -> Cell<T> {
Cell {
value: UnsafeCell::new(value),
- noshare: marker::NoShare,
+ noshare: marker::NoSync,
}
}
value: UnsafeCell<T>,
borrow: Cell<BorrowFlag>,
nocopy: marker::NoCopy,
- noshare: marker::NoShare,
+ noshare: marker::NoSync,
}
// Values [1, MAX-1] represent the number of `Ref` active
value: UnsafeCell::new(value),
borrow: Cell::new(UNUSED),
nocopy: marker::NoCopy,
- noshare: marker::NoShare,
+ noshare: marker::NoSync,
}
}
///
/// struct NotThreadSafe<T> {
/// value: UnsafeCell<T>,
-/// marker: marker::NoShare
+/// marker: marker::NoSync
/// }
/// ```
///
*/
+#[deprecated = "This has been renamed to Sync"]
+pub use Share = self::Sync;
+
/// Types able to be transferred across task boundaries.
#[lang="send"]
pub trait Send {
/// Types that can be safely shared between tasks when aliased.
///
-/// The precise definition is: a type `T` is `Share` if `&T` is
+/// The precise definition is: a type `T` is `Sync` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between tasks.
///
/// As one would expect, primitive types like `u8` and `f64` are all
-/// `Share`, and so are simple aggregate types containing them (like
-/// tuples, structs and enums). More instances of basic `Share` types
+/// `Sync`, and so are simple aggregate types containing them (like
+/// tuples, structs and enums). More instances of basic `Sync` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
-/// collection types. (Generic parameters need to be `Share` for their
-/// container to be `Share`.)
+/// collection types. (Generic parameters need to be `Sync` for their
+/// container to be `Sync`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
-/// `Share` (if `T` is `Share`) even though it seems that it might
+/// `Sync` (if `T` is `Sync`) even though it seems that it might
/// provide unsynchronised mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
///
-/// Types that are not `Share` are those that have "interior
+/// Types that are not `Sync` are those that have "interior
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
/// in `std::cell`. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// `&Cell<T>` can be `.set`, and do not ensure data races are
-/// impossible, hence they cannot be `Share`. A higher level example
-/// of a non-`Share` type is the reference counted pointer
+/// impossible, hence they cannot be `Sync`. A higher level example
+/// of a non-`Sync` type is the reference counted pointer
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
/// the `sync` crate do ensure that any mutation cannot cause data
-/// races. Hence these types are `Share`.
+/// races. Hence these types are `Sync`.
///
/// Users writing their own types with interior mutability (or anything
-/// else that is not thread-safe) should use the `NoShare` marker type
+/// else that is not thread-safe) should use the `NoSync` marker type
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
-/// consider the user-defined type to be `Share`. Any types with
+/// consider the user-defined type to be `Sync`. Any types with
/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
/// around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
+#[lang="sync"]
+#[cfg(not(stage0))]
+pub trait Sync {
+ // Empty
+}
+/// dox
#[lang="share"]
-pub trait Share {
+#[cfg(stage0)]
+pub trait Sync {
// Empty
}
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {
-
/// A marker type whose type parameter `T` is considered to be
/// covariant with respect to the type itself. This is (typically)
/// used to indicate that an instance of the type `T` is being stored
#[deriving(PartialEq,Clone)]
pub struct NoCopy;
- /// A type which is considered "not shareable", meaning that
+ /// A type which is considered "not sync", meaning that
/// its contents are not threadsafe, hence they cannot be
/// shared between tasks.
#[lang="no_share_bound"]
#[deriving(PartialEq,Clone)]
- pub struct NoShare;
+ pub struct NoSync;
/// A type which is considered managed by the GC. This is typically
/// embedded in other types.
//! ```
// Reexported core operators
-pub use kinds::{Copy, Send, Sized, Share};
+pub use kinds::{Copy, Send, Sized, Sync};
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop, Deref, DerefMut};
pub fn queue<T: Send>() -> (Consumer<T>, Producer<T>) {
let a = Arc::new(mpsc::Queue::new());
- (Consumer { inner: a.clone(), noshare: marker::NoShare },
- Producer { inner: a, noshare: marker::NoShare })
+ (Consumer { inner: a.clone(), noshare: marker::NoSync },
+ Producer { inner: a, noshare: marker::NoSync })
}
pub struct Producer<T> {
inner: Arc<mpsc::Queue<T>>,
- noshare: marker::NoShare,
+ noshare: marker::NoSync,
}
pub struct Consumer<T> {
inner: Arc<mpsc::Queue<T>>,
- noshare: marker::NoShare,
+ noshare: marker::NoSync,
}
impl<T: Send> Consumer<T> {
impl<T: Send> Clone for Producer<T> {
fn clone(&self) -> Producer<T> {
- Producer { inner: self.inner.clone(), noshare: marker::NoShare }
+ Producer { inner: self.inner.clone(), noshare: marker::NoSync }
}
}
match ecx.tcx.map.find(*id) {
Some(ast_map::NodeItem(i)) => {
match i.node {
- ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
+ ast::ItemFn(_, _, abi, ref generics, _)
+ if abi != abi::Rust && !generics.is_type_parameterized() => {
rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
}
_ => {}
param_bounds.builtin_bounds.add(ty::BoundCopy);
}
'T' => {
- param_bounds.builtin_bounds.add(ty::BoundShare);
+ param_bounds.builtin_bounds.add(ty::BoundSync);
}
'I' => {
param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
ty::BoundStatic => mywrite!(w, "O"),
ty::BoundSized => mywrite!(w, "Z"),
ty::BoundCopy => mywrite!(w, "P"),
- ty::BoundShare => mywrite!(w, "T"),
+ ty::BoundSync => mywrite!(w, "T"),
}
}
// Language items are items that represent concepts intrinsic to the language
// itself. Examples are:
//
-// * Traits that specify "kinds"; e.g. "Share", "Send".
+// * Traits that specify "kinds"; e.g. "Sync", "Send".
//
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
//
Some(ty::BoundSized)
} else if Some(id) == self.copy_trait() {
Some(ty::BoundCopy)
- } else if Some(id) == self.share_trait() {
- Some(ty::BoundShare)
+ } else if Some(id) == self.sync_trait() {
+ Some(ty::BoundSync)
} else {
None
}
SendTraitLangItem, "send", send_trait;
SizedTraitLangItem, "sized", sized_trait;
CopyTraitLangItem, "copy", copy_trait;
- ShareTraitLangItem, "share", share_trait;
+ SyncTraitLangItem, "sync", sync_trait;
DropTraitLangItem, "drop", drop_trait;
NoSendItem, "no_send_bound", no_send_bound;
NoCopyItem, "no_copy_bound", no_copy_bound;
- NoShareItem, "no_share_bound", no_share_bound;
+ NoSyncItem, "no_share_bound", no_share_bound;
ManagedItem, "managed_bound", managed_bound;
IteratorItem, "iterator", iterator;
}
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
-fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
+pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
ty: Type, output: ty::t) -> ValueRef {
let llfn: ValueRef = name.with_c_str(|buf| {
let _icx = push_ctxt("trans_item");
match item.node {
ast::ItemFn(ref decl, _fn_style, abi, ref generics, ref body) => {
- if abi != Rust {
- let llfndecl = get_item_val(ccx, item.id);
- foreign::trans_rust_fn_with_foreign_abi(
- ccx, &**decl, &**body, item.attrs.as_slice(), llfndecl, item.id);
- } else if !generics.is_type_parameterized() {
+ if !generics.is_type_parameterized() {
let llfn = get_item_val(ccx, item.id);
- trans_fn(ccx,
- &**decl,
- &**body,
- llfn,
- ¶m_substs::empty(),
- item.id,
- item.attrs.as_slice(),
- TranslateItems);
+ if abi != Rust {
+ foreign::trans_rust_fn_with_foreign_abi(ccx,
+ &**decl,
+ &**body,
+ item.attrs.as_slice(),
+ llfn,
+ ¶m_substs::empty(),
+ item.id,
+ None);
+ } else {
+ trans_fn(ccx,
+ &**decl,
+ &**body,
+ llfn,
+ ¶m_substs::empty(),
+ item.id,
+ item.attrs.as_slice(),
+ TranslateItems);
+ }
} else {
// Be sure to travel more than just one layer deep to catch nested
// items in blocks and such.
ty::BoundSend => unique_type_id.push_str("Send"),
ty::BoundSized => unique_type_id.push_str("Sized"),
ty::BoundCopy => unique_type_id.push_str("Copy"),
- ty::BoundShare => unique_type_id.push_str("Share"),
+ ty::BoundSync => unique_type_id.push_str("Sync"),
};
unique_type_id.push_char('+');
}
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
//
use middle::trans::type_of;
use middle::ty::FnSig;
use middle::ty;
+use middle::subst::Subst;
use std::cmp;
use libc::c_uint;
use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi};
// inline the one into the other. Of course we could just generate the
// correct code in the first place, but this is much simpler.
+pub fn decl_rust_fn_with_foreign_abi(ccx: &CrateContext,
+ t: ty::t,
+ name: &str)
+ -> ValueRef {
+ let tys = foreign_types_for_fn_ty(ccx, t);
+ let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
+ let cconv = match ty::get(t).sty {
+ ty::ty_bare_fn(ref fn_ty) => {
+ let c = llvm_calling_convention(ccx, fn_ty.abi);
+ c.unwrap_or(llvm::CCallConv)
+ }
+ _ => fail!("expected bare fn in decl_rust_fn_with_foreign_abi")
+ };
+ let llfn = base::decl_fn(ccx, name, cconv, llfn_ty, ty::mk_nil());
+ add_argument_attributes(&tys, llfn);
+ debug!("decl_rust_fn_with_foreign_abi(llfn_ty={}, llfn={})",
+ ccx.tn.type_to_string(llfn_ty), ccx.tn.val_to_string(llfn));
+ llfn
+}
+
pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
sp: Span,
sym: String,
body: &ast::Block,
attrs: &[ast::Attribute],
llwrapfn: ValueRef,
- id: ast::NodeId) {
+ param_substs: ¶m_substs,
+ id: ast::NodeId,
+ hash: Option<&str>) {
let _icx = push_ctxt("foreign::build_foreign_fn");
- let tys = foreign_types_for_id(ccx, id);
+
+ let fnty = ty::node_id_to_type(ccx.tcx(), id);
+ let mty = fnty.subst(ccx.tcx(), ¶m_substs.substs);
+ let tys = foreign_types_for_fn_ty(ccx, mty);
unsafe { // unsafe because we call LLVM operations
// Build up the Rust function (`foo0` above).
- let llrustfn = build_rust_fn(ccx, decl, body, attrs, id);
+ let llrustfn = build_rust_fn(ccx, decl, body, param_substs, attrs, id, hash);
// Build up the foreign wrapper (`foo` above).
- return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys, id);
+ return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys, mty);
}
fn build_rust_fn(ccx: &CrateContext,
decl: &ast::FnDecl,
body: &ast::Block,
+ param_substs: ¶m_substs,
attrs: &[ast::Attribute],
- id: ast::NodeId)
+ id: ast::NodeId,
+ hash: Option<&str>)
-> ValueRef {
let _icx = push_ctxt("foreign::foreign::build_rust_fn");
let tcx = ccx.tcx();
- let t = ty::node_id_to_type(tcx, id);
+ let t = ty::node_id_to_type(tcx, id).subst(
+ ccx.tcx(), ¶m_substs.substs);
let ps = ccx.tcx.map.with_path(id, |path| {
let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name));
- link::mangle(path.chain(abi.move_iter()), None)
+ link::mangle(path.chain(abi.move_iter()), hash)
});
// Compute the type that the function would have if it were just a
let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice());
base::set_llvm_fn_attrs(attrs, llfn);
- base::trans_fn(ccx, decl, body, llfn, ¶m_substs::empty(), id, [],
- TranslateItems);
+ base::trans_fn(ccx, decl, body, llfn, param_substs, id, [], TranslateItems);
llfn
}
llrustfn: ValueRef,
llwrapfn: ValueRef,
tys: &ForeignTypes,
- id: ast::NodeId) {
+ t: ty::t) {
let _icx = push_ctxt(
"foreign::trans_rust_fn_with_foreign_abi::build_wrap_fn");
let tcx = ccx.tcx();
- let t = ty::node_id_to_type(tcx, id);
-
debug!("build_wrap_fn(llrustfn={}, llwrapfn={}, t={})",
ccx.tn.val_to_string(llrustfn),
ccx.tn.val_to_string(llwrapfn),
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// 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.
//
use middle::trans::base::{trans_fn, decl_internal_rust_fn};
use middle::trans::base;
use middle::trans::common::*;
+use middle::trans::foreign;
use middle::ty;
use middle::typeck;
use util::ppaux::Repr;
monomorphizing.insert(fn_id, depth + 1);
}
- let s = ccx.tcx.map.with_path(fn_id.node, |path| {
+ let hash;
+ let s = {
let mut state = sip::SipState::new();
hash_id.hash(&mut state);
mono_ty.hash(&mut state);
- exported_name(path, format!("h{}", state.result()).as_slice())
- });
+ hash = format!("h{}", state.result());
+ ccx.tcx.map.with_path(fn_id.node, |path| {
+ exported_name(path, hash.as_slice())
+ })
+ };
+
debug!("monomorphize_fn mangled to {}", s);
// This shouldn't need to option dance.
let mut hash_id = Some(hash_id);
- let mk_lldecl = || {
- let lldecl = decl_internal_rust_fn(ccx, mono_ty, s.as_slice());
+ let mk_lldecl = |abi: abi::Abi| {
+ let lldecl = if abi != abi::Rust {
+ foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, s.as_slice())
+ } else {
+ decl_internal_rust_fn(ccx, mono_ty, s.as_slice())
+ };
+
ccx.monomorphized.borrow_mut().insert(hash_id.take_unwrap(), lldecl);
lldecl
};
ast_map::NodeItem(i) => {
match *i {
ast::Item {
- node: ast::ItemFn(ref decl, _, _, _, ref body),
+ node: ast::ItemFn(ref decl, _, abi, _, ref body),
..
} => {
- let d = mk_lldecl();
+ let d = mk_lldecl(abi);
set_llvm_fn_attrs(i.attrs.as_slice(), d);
- trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, [],
- IgnoreItems);
+
+ if abi != abi::Rust {
+ foreign::trans_rust_fn_with_foreign_abi(
+ ccx, &**decl, &**body, [], d, &psubsts, fn_id.node,
+ Some(hash.as_slice()));
+ } else {
+ trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, [],
+ IgnoreItems);
+ }
+
d
}
_ => {
let parent = ccx.tcx.map.get_parent(fn_id.node);
let tvs = ty::enum_variants(ccx.tcx(), local_def(parent));
let this_tv = tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
- let d = mk_lldecl();
+ let d = mk_lldecl(abi::Rust);
set_inline_hint(d);
match v.node.kind {
ast::TupleVariantKind(ref args) => {
d
}
ast_map::NodeMethod(mth) => {
- let d = mk_lldecl();
+ let d = mk_lldecl(abi::Rust);
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, [],
IgnoreItems);
ast_map::NodeTraitMethod(method) => {
match *method {
ast::Provided(mth) => {
- let d = mk_lldecl();
+ let d = mk_lldecl(abi::Rust);
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d,
&psubsts, mth.id, [], IgnoreItems);
}
}
ast_map::NodeStructCtor(struct_def) => {
- let d = mk_lldecl();
+ let d = mk_lldecl(abi::Rust);
set_inline_hint(d);
base::trans_tuple_struct(ccx,
struct_def.fields.as_slice(),
ccx.monomorphizing.borrow_mut().insert(fn_id, depth);
debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
- (lldecl, false)
+ (lldecl, true)
}
// Used to identify cached monomorphized functions and vtables
BoundSend,
BoundSized,
BoundCopy,
- BoundShare,
+ BoundSync,
}
pub fn empty_builtin_bounds() -> BuiltinBounds {
set.add(BoundStatic);
set.add(BoundSend);
set.add(BoundSized);
- set.add(BoundShare);
+ set.add(BoundSync);
set
}
ReachesBorrowed = 0b0000_0010__0000_0000__0000,
// ReachesManaged /* see [1] below */ = 0b0000_0100__0000_0000__0000,
ReachesMutable = 0b0000_1000__0000_0000__0000,
- ReachesNoShare = 0b0001_0000__0000_0000__0000,
+ ReachesNoSync = 0b0001_0000__0000_0000__0000,
ReachesAll = 0b0001_1111__0000_0000__0000,
// Things that cause values to *move* rather than *copy*
// Things that prevent values from being considered sized
Nonsized = 0b0000_0000__0000_0000__0001,
- // Things that prevent values from being shared
- Nonsharable = 0b0001_0000__0000_0000__0000,
+ // Things that prevent values from being sync
+ Nonsync = 0b0001_0000__0000_0000__0000,
// Things that make values considered not POD (would be same
// as `Moves`, but for the fact that managed data `@` is
BoundSend => self.is_sendable(cx),
BoundSized => self.is_sized(cx),
BoundCopy => self.is_copy(cx),
- BoundShare => self.is_sharable(cx),
+ BoundSync => self.is_sync(cx),
}
}
!self.intersects(TC::Nonsendable)
}
- pub fn is_sharable(&self, _: &ctxt) -> bool {
- !self.intersects(TC::Nonsharable)
+ pub fn is_sync(&self, _: &ctxt) -> bool {
+ !self.intersects(TC::Nonsync)
}
pub fn owns_managed(&self) -> bool {
} else if Some(did) == cx.lang_items.no_copy_bound() {
tc | TC::OwnsAffine
} else if Some(did) == cx.lang_items.no_share_bound() {
- tc | TC::ReachesNoShare
+ tc | TC::ReachesNoSync
} else if Some(did) == cx.lang_items.unsafe_type() {
// FIXME(#13231): This shouldn't be needed after
// opt-in built-in bounds are implemented.
- (tc | TC::InteriorUnsafe) - TC::Nonsharable
+ (tc | TC::InteriorUnsafe) - TC::Nonsync
} else {
tc
}
BoundSend => TC::Nonsendable,
BoundSized => TC::Nonsized,
BoundCopy => TC::Noncopy,
- BoundShare => TC::Nonsharable,
+ BoundSync => TC::Nonsync,
};
});
return tc;
}
}
-fn ensure_generics_abi(ccx: &CrateCtxt,
- span: Span,
- abi: abi::Abi,
- generics: &ast::Generics) {
- if generics.ty_params.len() > 0 &&
- !(abi == abi::Rust || abi == abi::RustIntrinsic) {
- span_err!(ccx.tcx.sess, span, E0123,
- "foreign functions may not use type parameters");
- }
-}
-
pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
let tcx = ccx.tcx;
debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
},
ast::ItemTy(_, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
- let pty = ty_of_item(ccx, it);
- write_ty_to_tcx(tcx, it.id, pty.ty);
- },
- ast::ItemFn(_, _, abi, ref generics, _) => {
- ensure_generics_abi(ccx, it.span, abi, generics);
- let pty = ty_of_item(ccx, it);
- write_ty_to_tcx(tcx, it.id, pty.ty);
+ let tpt = ty_of_item(ccx, it);
+ write_ty_to_tcx(tcx, it.id, tpt.ty);
},
_ => {
// This call populates the type cache with the converted type
ty::BoundSend => "Send".to_string(),
ty::BoundSized => "Sized".to_string(),
ty::BoundCopy => "Copy".to_string(),
- ty::BoundShare => "Share".to_string(),
+ ty::BoundSync => "Sync".to_string(),
});
}
for t in self.trait_bounds.iter() {
ty::BoundSend => "Send".to_string(),
ty::BoundSized => "Sized".to_string(),
ty::BoundCopy => "Copy".to_string(),
- ty::BoundShare => "Share".to_string(),
+ ty::BoundSync => "Sync".to_string(),
}
}
}
ty::BoundCopy =>
(tcx.lang_items.copy_trait().unwrap(),
external_path("Copy", &empty)),
- ty::BoundShare =>
- (tcx.lang_items.share_trait().unwrap(),
- external_path("Share", &empty)),
+ ty::BoundSync =>
+ (tcx.lang_items.sync_trait().unwrap(),
+ external_path("Sync", &empty)),
};
let fqn = csearch::get_item_path(tcx, did);
let fqn = fqn.move_iter().map(|i| i.to_string()).collect();
// refcount of 0 means uninitialized value, 1 means initialized, 2+ means
// borrowed.
// NB: we use UnsafeCell instead of Cell because Ref should be allowed to
- // be Share. The only mutation occurs when a Ref is created or destroyed,
+ // be Sync. The only mutation occurs when a Ref is created or destroyed,
// so there's no issue with &Ref being thread-safe.
refcount: UnsafeCell<uint>
}
#![experimental]
// Reexported core operators
-#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Share};
+#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync};
#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor};
#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut};
//!
//! [1]: http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync
//!
-//! Atomic variables are safe to share between threads (they implement `Share`)
+//! Atomic variables are safe to share between threads (they implement `Sync`)
//! but they do not themselves provide the mechanism for sharing. The most
//! common way to share an atomic variable is to put it into an `Arc` (an
//! atomically-reference-counted shared pointer).
inner: UnsafeCell<Flavor<T>>,
receives: Cell<uint>,
// can't share in an arc
- marker: marker::NoShare,
+ marker: marker::NoSync,
}
/// An iterator over messages on a receiver, this iterator will block
inner: UnsafeCell<Flavor<T>>,
sends: Cell<uint>,
// can't share in an arc
- marker: marker::NoShare,
+ marker: marker::NoSync,
}
/// The sending-half of Rust's synchronous channel type. This half can only be
pub struct SyncSender<T> {
inner: Arc<UnsafeCell<sync::Packet<T>>>,
// can't share in an arc
- marker: marker::NoShare,
+ marker: marker::NoSync,
}
/// This enumeration is the list of the possible reasons that try_recv could not
Sender {
inner: UnsafeCell::new(inner),
sends: Cell::new(0),
- marker: marker::NoShare,
+ marker: marker::NoSync,
}
}
impl<T: Send> SyncSender<T> {
fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
- SyncSender { inner: inner, marker: marker::NoShare }
+ SyncSender { inner: inner, marker: marker::NoSync }
}
/// Sends a value on this synchronous channel.
impl<T: Send> Receiver<T> {
fn new(inner: Flavor<T>) -> Receiver<T> {
- Receiver { inner: UnsafeCell::new(inner), receives: Cell::new(0), marker: marker::NoShare }
+ Receiver { inner: UnsafeCell::new(inner), receives: Cell::new(0), marker: marker::NoSync }
}
/// Blocks waiting for a value on this receiver
/// There may only be one worker per deque.
pub struct Worker<T> {
deque: Arc<Deque<T>>,
- noshare: marker::NoShare,
+ noshare: marker::NoSync,
}
/// The stealing half of the work-stealing deque. Stealers have access to the
/// `steal` method.
pub struct Stealer<T> {
deque: Arc<Deque<T>>,
- noshare: marker::NoShare,
+ noshare: marker::NoSync,
}
/// When stealing some data, this is an enumeration of the possible outcomes.
pub fn deque(&self) -> (Worker<T>, Stealer<T>) {
let a = Arc::new(Deque::new(self.clone()));
let b = a.clone();
- (Worker { deque: a, noshare: marker::NoShare },
- Stealer { deque: b, noshare: marker::NoShare })
+ (Worker { deque: a, noshare: marker::NoSync },
+ Stealer { deque: b, noshare: marker::NoSync })
}
fn alloc(&mut self, bits: uint) -> Box<Buffer<T>> {
impl<T: Send> Clone for Stealer<T> {
fn clone(&self) -> Stealer<T> {
- Stealer { deque: self.deque.clone(), noshare: marker::NoShare }
+ Stealer { deque: self.deque.clone(), noshare: marker::NoSync }
}
}
_guard: raw::RWLockReadGuard<'a>,
}
-impl<T: Send + Share> RWLock<T> {
+impl<T: Send + Sync> RWLock<T> {
/// Create a reader/writer lock with the supplied data.
pub fn new(user_data: T) -> RWLock<T> {
RWLock::new_with_condvars(user_data, 1)
}
}
-impl<'a, T: Send + Share> RWLockWriteGuard<'a, T> {
+impl<'a, T: Send + Sync> RWLockWriteGuard<'a, T> {
/// Consumes this write lock token, returning a new read lock token.
///
/// This will allow pending readers to come into the lock.
}
}
-impl<'a, T: Send + Share> Deref<T> for RWLockReadGuard<'a, T> {
+impl<'a, T: Send + Sync> Deref<T> for RWLockReadGuard<'a, T> {
fn deref<'a>(&'a self) -> &'a T { self._data }
}
-impl<'a, T: Send + Share> Deref<T> for RWLockWriteGuard<'a, T> {
+impl<'a, T: Send + Sync> Deref<T> for RWLockWriteGuard<'a, T> {
fn deref<'a>(&'a self) -> &'a T { &*self._data }
}
-impl<'a, T: Send + Share> DerefMut<T> for RWLockWriteGuard<'a, T> {
+impl<'a, T: Send + Sync> DerefMut<T> for RWLockWriteGuard<'a, T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self._data }
}
// The building-block used to make semaphores, mutexes, and rwlocks.
struct Sem<Q> {
lock: mutex::Mutex,
- // n.b, we need Sem to be `Share`, but the WaitQueue type is not send/share
+ // n.b, we need Sem to be `Sync`, but the WaitQueue type is not send/share
// (for good reason). We have an internal invariant on this semaphore,
// however, that the queue is never accessed outside of a locked
// context.
/// The AST represents all type param bounds as types.
/// typeck::collect::compute_bounds matches these against
/// the "special" built-in traits (see middle::lang_items) and
-/// detects Copy, Send and Share.
+/// detects Copy, Send and Sync.
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub enum TyParamBound {
TraitTyParamBound(TraitRef),
match tname.get() {
"Copy" => "Copy",
"Send" => "Send",
- "Share" => "Share",
+ "Sync" => "Sync",
ref tname => {
cx.span_bug(span,
format!("expected built-in trait name but \
"FromPrimitive" => expand!(primitive::expand_deriving_from_primitive),
"Send" => expand!(bounds::expand_deriving_bound),
- "Share" => expand!(bounds::expand_deriving_bound),
+ "Sync" => expand!(bounds::expand_deriving_bound),
"Copy" => expand!(bounds::expand_deriving_bound),
ref tname => {
}
#[unsafe_destructor]
-impl<T: Share> Drop for arc_destruct<T> {
+impl<T: Sync> Drop for arc_destruct<T> {
fn drop(&mut self) {}
}
-fn arc_destruct<T: Share>(data: int) -> arc_destruct<T> {
+fn arc_destruct<T: Sync>(data: int) -> arc_destruct<T> {
arc_destruct {
_data: data
}
}
-fn arc<T: Share>(_data: T) -> arc_destruct<T> {
+fn arc<T: Sync>(_data: T) -> arc_destruct<T> {
arc_destruct(0)
}
#![crate_type="lib"]
-pub trait RequiresShare : Share { }
+pub trait RequiresShare : Sync { }
pub trait RequiresRequiresShareAndSend : RequiresShare + Send { }
pub trait RequiresCopy : Copy { }
// Test for traits that inherit from multiple builtin kinds at once,
// testing that all such kinds must be present on implementing types.
-trait Foo : Send+Share { }
+trait Foo : Send+Sync { }
-impl <T: Share> Foo for (T,) { } //~ ERROR cannot implement this trait
+impl <T: Sync> Foo for (T,) { } //~ ERROR cannot implement this trait
impl <T: Send> Foo for (T,T) { } //~ ERROR cannot implement this trait
-impl <T: Send+Share> Foo for (T,T,T) { } // (ok)
+impl <T: Send+Sync> Foo for (T,T,T) { } // (ok)
fn main() { }
struct X<T>(T);
-impl <T:Share> RequiresShare for X<T> { }
+impl <T:Sync> RequiresShare for X<T> { }
-impl <T:Share> RequiresRequiresShareAndSend for X<T> { } //~ ERROR cannot implement this trait
+impl <T:Sync> RequiresRequiresShareAndSend for X<T> { } //~ ERROR cannot implement this trait
fn main() { }
// Tests (negatively) the ability for the Self type in default methods
// to use capabilities granted by builtin kinds as supertraits.
-trait Foo : Share {
+trait Foo : Sync {
fn foo(self, mut chan: Sender<Self>) {
chan.send(self); //~ ERROR does not fulfill `Send`
}
}
-impl <T: Share> Foo for T { }
+impl <T: Sync> Foo for T { }
fn main() {
let (tx, rx) = channel();
trait Foo : Send { }
-impl <T: Share> Foo for T { } //~ ERROR cannot implement this trait
+impl <T: Sync> Foo for T { } //~ ERROR cannot implement this trait
fn main() { }
fn take_any(_: ||:) {
}
-fn take_const_owned(_: ||:Share+Send) {
+fn take_const_owned(_: ||:Sync+Send) {
}
fn give_any(f: ||:) {
fn give_owned(f: ||:Send) {
take_any(f);
- take_const_owned(f); //~ ERROR expected bounds `Send+Share` but found bounds `Send`
+ take_const_owned(f); //~ ERROR expected bounds `Send+Sync` but found bounds `Send`
}
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn test<T: Share>() {}
+fn test<T: Sync>() {}
fn main() {
- test::<Sender<int>>(); //~ ERROR: does not fulfill `Share`
- test::<Receiver<int>>(); //~ ERROR: does not fulfill `Share`
- test::<Sender<int>>(); //~ ERROR: does not fulfill `Share`
+ test::<Sender<int>>(); //~ ERROR: does not fulfill `Sync`
+ test::<Receiver<int>>(); //~ ERROR: does not fulfill `Sync`
+ test::<Sender<int>>(); //~ ERROR: does not fulfill `Sync`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[deriving(Share(Bad),Send,Copy)]
+#[deriving(Sync(Bad),Send,Copy)]
//~^ ERROR unexpected value in deriving, expected a trait
struct Test;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern "C" fn foo<T>() {} //~ERROR foreign functions may not use type parameters
+extern {
+ fn foo<T>(); //~ ERROR foreign items may not have type parameters
+}
fn main() {
- let _ = foo::<int>;
+ foo::<i32>();
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test this should fail to compile (#15844)
+
+#[no_mangle]
+fn foo<T>() {} //~ ERROR generic functions must be mangled
+
+#[no_mangle]
+extern fn foo<T>() {} //~ ERROR generic functions must be mangled
+
}
impl A for E {
- fn b<F: Share, G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Share`
+ fn b<F: Sync, G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Sync`
}
fn main() {}
use std::kinds::marker;
-fn foo<P: Share>(p: P) { }
+fn foo<P: Sync>(p: P) { }
fn main()
{
- foo(marker::NoShare); //~ ERROR does not fulfill `Share`
+ foo(marker::NoSync); //~ ERROR does not fulfill `Sync`
}
use std::cell::RefCell;
-fn f<T: Share>(_: T) {}
+fn f<T: Sync>(_: T) {}
fn main() {
let x = RefCell::new(0i);
- f(x); //~ ERROR: which does not fulfill `Share`
+ f(x); //~ ERROR: which does not fulfill `Sync`
}
use std::kinds::marker;
-enum Foo { A(marker::NoShare) }
+enum Foo { A(marker::NoSync) }
-fn bar<T: Share>(_: T) {}
+fn bar<T: Sync>(_: T) {}
fn main() {
- let x = A(marker::NoShare);
+ let x = A(marker::NoSync);
bar(&x); //~ ERROR type parameter with an incompatible type
}
use std::kinds::marker;
-enum Foo { A(marker::NoShare) }
+enum Foo { A(marker::NoSync) }
-fn bar<T: Share>(_: T) {}
+fn bar<T: Sync>(_: T) {}
fn main() {
- let x = A(marker::NoShare);
+ let x = A(marker::NoSync);
bar(x);
//~^ ERROR instantiating a type parameter with an incompatible type `Foo`,
- // which does not fulfill `Share`
+ // which does not fulfill `Sync`
}
use std::rc::Rc;
use std::cell::RefCell;
-fn bar<T: Share>(_: T) {}
+fn bar<T: Sync>(_: T) {}
fn main() {
let x = Rc::new(RefCell::new(5i));
bar(x);
//~^ ERROR instantiating a type parameter with an incompatible type
- // `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Share`
+ // `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Sync`
}
use std::kinds::marker;
-struct Foo { a: int, m: marker::NoShare }
+struct Foo { a: int, m: marker::NoSync }
-fn bar<T: Share>(_: T) {}
+fn bar<T: Sync>(_: T) {}
fn main() {
- let x = Foo { a: 5, m: marker::NoShare };
+ let x = Foo { a: 5, m: marker::NoSync };
bar(x);
//~^ ERROR instantiating a type parameter with an incompatible type `Foo`,
- // which does not fulfill `Share`
+ // which does not fulfill `Sync`
}
// except according to those terms.
fn is_send<T: Send>() {}
-fn is_freeze<T: Share>() {}
+fn is_freeze<T: Sync>() {}
fn is_static<T: 'static>() {}
fn main() {
fn a(_x: Box<Foo+Send>) {
}
-fn c(x: Box<Foo+Share+Send>) {
+fn c(x: Box<Foo+Sync+Send>) {
a(x);
}
fn b(_x: &'static Foo) { // should be same as &'static Foo+'static
}
-fn c(x: Box<Foo+Share>) {
+fn c(x: Box<Foo+Sync>) {
a(x); //~ ERROR expected bounds `Send`
}
-fn d(x: &'static Foo+Share) {
+fn d(x: &'static Foo+Sync) {
b(x); //~ ERROR expected bounds `'static`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Verify that UnsafeCell is *always* share regardles `T` is share.
+// Verify that UnsafeCell is *always* sync regardles `T` is sync.
// ignore-tidy-linelength
use std::cell::UnsafeCell;
use std::kinds::marker;
-struct MyShare<T> {
+struct MySync<T> {
u: UnsafeCell<T>
}
-struct NoShare {
- m: marker::NoShare
+struct NoSync {
+ m: marker::NoSync
}
-fn test<T: Share>(s: T){
+fn test<T: Sync>(s: T){
}
fn main() {
- let us = UnsafeCell::new(MyShare{u: UnsafeCell::new(0i)});
+ let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0i)});
test(us);
- let uns = UnsafeCell::new(NoShare{m: marker::NoShare});
+ let uns = UnsafeCell::new(NoSync{m: marker::NoSync});
test(uns);
- let ms = MyShare{u: uns};
+ let ms = MySync{u: uns};
test(ms);
- let ns = NoShare{m: marker::NoShare};
+ let ns = NoSync{m: marker::NoSync};
test(ns);
- //~^ ERROR instantiating a type parameter with an incompatible type `NoShare`, which does not fulfill `Share`
+ //~^ ERROR instantiating a type parameter with an incompatible type `NoSync`, which does not fulfill `Sync`
}
trait Tr { }
impl Tr for int { }
-fn foo(x: Box<Tr+ Share>) -> Box<Tr+ Share> { x }
+fn foo(x: Box<Tr+ Sync>) -> Box<Tr+ Sync> { x }
fn main() {
- let x: Box<Tr+ Share>;
+ let x: Box<Tr+ Sync>;
- box() 1i as Box<Tr+ Share>;
+ box() 1i as Box<Tr+ Sync>;
}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
+ $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
+ $(RUSTC) testcrate.rs -L $(TMPDIR)
+ $(RUSTC) test.rs -L $(TMPDIR)
+ $(call RUN,test) || exit 1
--- /dev/null
+#include <stdint.h>
+
+typedef struct TestStruct {
+ uint8_t x;
+ int32_t y;
+} TestStruct;
+
+typedef int callback(TestStruct s);
+
+uint32_t call(callback *c) {
+ TestStruct s;
+ s.x = 'a';
+ s.y = 3;
+
+ return c(s);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate testcrate;
+
+extern "C" fn bar<T>(ts: testcrate::TestStruct<T>) -> T { ts.y }
+
+#[link(name = "test")]
+extern {
+ fn call(c: extern "C" fn(testcrate::TestStruct<i32>) -> i32) -> i32;
+}
+
+fn main() {
+ // Let's test calling it cross crate
+ let back = unsafe {
+ testcrate::call(testcrate::foo::<i32>)
+ };
+ assert_eq!(3, back);
+
+ // And just within this crate
+ let back = unsafe {
+ call(bar::<i32>)
+ };
+ assert_eq!(3, back);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+
+#[repr(C)]
+pub struct TestStruct<T> {
+ pub x: u8,
+ pub y: T
+}
+
+pub extern "C" fn foo<T>(ts: TestStruct<T>) -> T { ts.y }
+
+#[link(name = "test")]
+extern {
+ pub fn call(c: extern "C" fn(TestStruct<i32>) -> i32) -> i32;
+}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
+ $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
+ $(RUSTC) test.rs -L $(TMPDIR)
+ $(call RUN,test) || exit 1
--- /dev/null
+#include <stdint.h>
+
+uint32_t foo();
+uint32_t bar();
+
+uint32_t add() {
+ return foo() + bar();
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[no_mangle]
+pub extern "C" fn foo() -> i32 { 3 }
+
+#[no_mangle]
+pub extern "C" fn bar() -> i32 { 5 }
+
+#[link(name = "test", kind = "static")]
+extern {
+ fn add() -> i32;
+}
+
+fn main() {
+ let back = unsafe { add() };
+ assert_eq!(8, back);
+}
#[deriving(PartialEq)]
struct X<T>(T);
-impl <T: Share> RequiresShare for X<T> { }
-impl <T: Share+Send> RequiresRequiresShareAndSend for X<T> { }
+impl <T: Sync> RequiresShare for X<T> { }
+impl <T: Sync+Send> RequiresRequiresShareAndSend for X<T> { }
fn foo<T: RequiresRequiresShareAndSend>(val: T, chan: Sender<T>) {
chan.send(val);
struct X<T>(T);
-impl <T:Share> RequiresShare for X<T> { }
+impl <T:Sync> RequiresShare for X<T> { }
-impl <T:Share+Send> RequiresRequiresShareAndSend for X<T> { }
+impl <T:Sync+Send> RequiresRequiresShareAndSend for X<T> { }
impl <T:Copy> RequiresCopy for X<T> { }
a: ||: 'a,
b: ||: 'static,
c: <'b>||: 'a,
- d: ||: 'a + Share,
- e: <'b>|int|: 'a + Share -> &'b f32,
+ d: ||: 'a + Sync,
+ e: <'b>|int|: 'a + Sync -> &'b f32,
f: proc(),
- g: proc(): 'static + Share,
- h: proc<'b>(int): Share -> &'b f32,
+ g: proc(): 'static + Sync,
+ h: proc<'b>(int): Sync -> &'b f32,
}
fn f<'a>(a: &'a int, f: <'b>|&'b int| -> &'b int) -> &'a int {
foo::<|| -> ()>();
foo::<||:>();
foo::<||:'b>();
- foo::<||:'b + Share>();
- foo::<||:Share>();
- foo::< <'a>|int, f32, &'a int|:'b + Share -> &'a int>();
+ foo::<||:'b + Sync>();
+ foo::<||:Sync>();
+ foo::< <'a>|int, f32, &'a int|:'b + Sync -> &'a int>();
foo::<proc()>();
foo::<proc() -> ()>();
foo::<proc():'static>();
- foo::<proc():Share>();
- foo::<proc<'a>(int, f32, &'a int):'static + Share -> &'a int>();
+ foo::<proc():Sync>();
+ foo::<proc<'a>(int, f32, &'a int):'static + Sync -> &'a int>();
foo::<<'a>||>();
// are const.
-fn foo<T: Share>(x: T) -> T { x }
+fn foo<T: Sync>(x: T) -> T { x }
struct F { field: int }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[deriving(Share,Send,Copy)]
+#[deriving(Sync,Send,Copy)]
struct Test;
pub fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern "C" fn foo<T: Int>(a: T, b: T) -> T { a + b }
+
+fn main() {
+ assert_eq!(99u8, foo(255u8, 100u8));
+ assert_eq!(99u16, foo(65535u16, 100u16));
+}
// than the traits require.
trait A {
- fn b<C:Share,D>(x: C) -> C;
+ fn b<C:Sync,D>(x: C) -> C;
}
struct E {
}
fn foo1<T>(_: &A<T> + Send) {}
-fn foo2<T>(_: Box<A<T> + Send + Share>) {}
+fn foo2<T>(_: Box<A<T> + Send + Sync>) {}
fn foo3<T>(_: Box<B<int, uint> + 'static>) {}
fn foo4<'a, T>(_: Box<C<'a, T> + 'static + Send>) {}
fn foo5<'a, T>(_: Box<foo::D<'a, T> + 'static + Send>) {}
fn bar<T>(_: T) {}
fn is_send<T: Send>() {}
-fn is_freeze<T: Share>() {}
+fn is_freeze<T: Sync>() {}
fn is_static<T: 'static>() {}
pub fn main() {
foo::<proc()>();
foo::<proc()>();
foo::<proc():Send>();
- foo::<proc():Send + Share>();
- foo::<proc():'static + Send + Share>();
+ foo::<proc():Send + Sync>();
+ foo::<proc():'static + Send + Sync>();
is_send::<proc():Send>();
- is_freeze::<proc():Share>();
+ is_freeze::<proc():Sync>();
is_static::<proc():'static>();
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-macos apparently gargantuan mmap requests are ok?
-
-#![feature(phase)]
-
-#[phase(plugin)]
-extern crate green;
-extern crate native;
-
-use std::task::TaskBuilder;
-use native::NativeTaskBuilder;
-
-green_start!(main)
-
-fn main() {
- test();
-
- let (tx, rx) = channel();
- TaskBuilder::new().native().spawn(proc() {
- tx.send(test());
- });
- rx.recv();
-}
-
-#[cfg(not(target_word_size = "64"))]
-fn test() {}
-
-#[cfg(target_word_size = "64")]
-fn test() {
- let (tx, rx) = channel();
- spawn(proc() {
- TaskBuilder::new().stack_size(1024 * 1024 * 1024 * 64).spawn(proc() {
- });
- tx.send(());
- });
-
- assert!(rx.recv_opt().is_err());
-}
fn b(_x: Box<Foo+Send>) {
}
-fn c(x: Box<Foo+Share+Send>) {
+fn c(x: Box<Foo+Sync+Send>) {
e(x);
}
swim_speed: 998,
name: "alec_guinness".to_string(),
};
- let arc = Arc::new(vec!(box catte as Box<Pet+Share+Send>,
- box dogge1 as Box<Pet+Share+Send>,
- box fishe as Box<Pet+Share+Send>,
- box dogge2 as Box<Pet+Share+Send>));
+ let arc = Arc::new(vec!(box catte as Box<Pet+Sync+Send>,
+ box dogge1 as Box<Pet+Sync+Send>,
+ box fishe as Box<Pet+Sync+Send>,
+ box dogge2 as Box<Pet+Sync+Send>));
let (tx1, rx1) = channel();
let arc1 = arc.clone();
task::spawn(proc() { check_legs(arc1); tx1.send(()); });
rx3.recv();
}
-fn check_legs(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
+fn check_legs(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
let mut legs = 0;
for pet in arc.iter() {
legs += pet.num_legs();
}
assert!(legs == 12);
}
-fn check_names(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
+fn check_names(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
for pet in arc.iter() {
pet.name(|name| {
assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
})
}
}
-fn check_pedigree(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
+fn check_pedigree(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
for pet in arc.iter() {
assert!(pet.of_good_pedigree());
}