Skip to content

Rollup of 6 pull requests #26002

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jun 4, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -3599,6 +3599,147 @@ The notation `&self` is a shorthand for `self: &Self`. In this case,
in the impl, `Self` refers to the value of type `String` that is the
receiver for a call to the method `make_string`.

## Subtyping

Subtyping is implicit and can occur at any stage in type checking or
inference. Subtyping in Rust is very restricted and occurs only due to
variance with respect to lifetimes and between types with higher ranked
lifetimes. If we were to erase lifetimes from types, then the only subtyping
would be due to type equality.

Consider the following example: string literals always have `'static`
lifetime. Nevertheless, we can assign `s` to `t`:

```
fn bar<'a>() {
let s: &'static str = "hi";
let t: &'a str = s;
}
```
Since `'static` "lives longer" than `'a`, `&'static str` is a subtype of
`&'a str`.

## Type coercions

Coercions are defined in [RFC401]. A coercion is implicit and has no syntax.

[RFC401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md

### Coercion sites

A coercion can only occur at certain coercion sites in a program; these are
typically places where the desired type is explicit or can be dervied by
propagation from explicit types (without type inference). Possible coercion
sites are:

* `let` statements where an explicit type is given.

In `let _: U = e;`, `e` is coerced to have type `U`.

* `static` and `const` statements (similar to `let` statements).

* arguments for function calls.

The value being coerced is the
actual parameter and it is coerced to the type of the formal parameter. For
example, let `foo` be defined as `fn foo(x: U) { ... }` and call it as
`foo(e);`. Then `e` is coerced to have type `U`;

* instantiations of struct or variant fields.

Assume we have a `struct
Foo { x: U }` and instantiate it as `Foo { x: e }`. Then `e` is coerced to
have type `U`.

* function results (either the final line of a block if it is not semicolon
terminated or any expression in a `return` statement).

In `fn foo() -> U { e }`, `e` is coerced to to have type `U`.

If the expression in one of these coercion sites is a coercion-propagating
expression, then the relevant sub-expressions in that expression are also
coercion sites. Propagation recurses from these new coercion sites.
Propagating expressions and their relevant sub-expressions are:

* array literals, where the array has type `[U; n]`. Each sub-expression in
the array literal is a coercion site for coercion to type `U`.

* array literals with repeating syntax, where the array has type `[U; n]`. The
repeated sub-expression is a coercion site for coercion to type `U`.

* tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`.
Each sub-expression is a coercion site to the respective type, e.g. the
zeroth sub-expression is a coercion site to type `U_0`.

* parenthesised sub-expressions (`(e)`). If the expression has type `U`, then
the sub-expression is a coercion site to `U`.

* blocks. If a block has type `U`, then the last expression in the block (if
it is not semicolon-terminated) is a coercion site to `U`. This includes
blocks which are part of control flow statements, such as `if`/`else`, if
the block has a known type.

### Coercion types

Coercion is allowed between the following types:

* `T` to `U` if `T` is a subtype of `U` (*reflexive case*).

* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3`
(*transitive case*).

Note that this is not fully supported yet

* `&mut T` to `&T`.

* `*mut T` to `*const T`.

* `&T` to `*const T`.

* `&mut T` to `*mut T`.

* `&T` to `&U` if `T` implements `Deref<Target = U>`. For example:

```rust
use std::ops::Deref;

struct CharContainer {
value: char
}

impl Deref for CharContainer {
type Target = char;

fn deref<'a>(&'a self) -> &'a char {
&self.value
}
}

fn foo(arg: &char) {}

fn main() {
let x = &mut CharContainer { value: 'y' };
foo(x); //&mut CharContainer is coerced to &char.
}
```
* `&mut T` to `&mut U` if `T` implements `DerefMut<Target = U>`.

* TyCtor(`T`) to TyCtor(coerce_inner(`T`)), where TyCtor(`T`) is one of
- `&T`
- `&mut T`
- `*const T`
- `*mut T`
- `Box<T>`

and where
- coerce_inner(`[T, ..n]`) = `[T]`
- coerce_inner(`T`) = `U` where `T` is a concrete type which implements the
trait `U`.

In the future, coerce_inner will be recursively extended to tuples and
structs. In addition, coercions from sub-traits to super-traits will be
added. See [RFC401] for more details.

# Special traits

Several traits define special evaluation behavior.
Expand Down
4 changes: 3 additions & 1 deletion src/libcore/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@
//! }
//! ```
//!
//! `try!` is imported by the prelude, and is available everywhere.
//! `try!` is imported by the prelude and is available everywhere, but it can only
//! be used in functions that return `Result` because of the early return of
//! `Err` that it provides.

#![stable(feature = "rust1", since = "1.0.0")]

Expand Down
12 changes: 5 additions & 7 deletions src/librustc_typeck/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,14 +238,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
/// Let `v` be some value (either temporary or named) and 'a be some
/// lifetime (scope). If the type of `v` owns data of type `D`, where
///
/// (1.) `D` has a lifetime- or type-parametric Drop implementation, and
/// (2.) the structure of `D` can reach a reference of type `&'a _`, and
/// (3.) either:
///
/// (A.) the Drop impl for `D` instantiates `D` at 'a directly,
/// * (1.) `D` has a lifetime- or type-parametric Drop implementation, and
/// * (2.) the structure of `D` can reach a reference of type `&'a _`, and
/// * (3.) either:
/// * (A.) the Drop impl for `D` instantiates `D` at 'a directly,
/// i.e. `D<'a>`, or,
///
/// (B.) the Drop impl for `D` has some type parameter with a
/// * (B.) the Drop impl for `D` has some type parameter with a
/// trait bound `T` where `T` is a trait that has at least
/// one method,
///
Expand Down
29 changes: 28 additions & 1 deletion src/libstd/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,34 @@ macro_rules! println {
}

/// Helper macro for unwrapping `Result` values while returning early with an
/// error if the value of the expression is `Err`.
/// error if the value of the expression is `Err`. Can only be used in
/// functions that return `Result` because of the early return of `Err` that
/// it provides.
///
/// # Examples
///
/// ```
/// use std::io;
/// use std::fs::File;
/// use std::io::prelude::*;
///
/// fn write_to_file_using_try() -> Result<(), io::Error> {
/// let mut file = try!(File::create("my_best_friends.txt"));
/// try!(file.write_all(b"This is a list of my best friends."));
/// println!("I wrote to the file");
/// Ok(())
/// }
/// // This is equivalent to:
/// fn write_to_file_using_match() -> Result<(), io::Error> {
/// let mut file = try!(File::create("my_best_friends.txt"));
/// match file.write_all(b"This is a list of my best friends.") {
/// Ok(_) => (),
/// Err(e) => return Err(e),
/// }
/// println!("I wrote to the file");
/// Ok(())
/// }
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! try {
Expand Down
4 changes: 4 additions & 0 deletions src/libstd/sync/rwlock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ use sys_common::rwlock as sys;
/// of the underlying data (exclusive access) and the read portion of this lock
/// typically allows for read-only access (shared access).
///
/// The priority policy of the lock is dependent on the underlying operating
/// system's implementation, and this type does not guarantee that any
/// particular policy will be used.
///
/// The type parameter `T` represents the data that this lock protects. It is
/// required that `T` satisfies `Send` to be shared across threads and `Sync` to
/// allow concurrent access through readers. The RAII guards returned from the
Expand Down
3 changes: 1 addition & 2 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2070,10 +2070,9 @@ impl<'a> Parser<'a> {
}
_ => {
if try!(self.eat_lt()){

let (qself, path) =
try!(self.parse_qualified_path(LifetimeAndTypesWithColons));

hi = path.span.hi;
return Ok(self.mk_expr(lo, hi, ExprPath(Some(qself), path)));
}
if try!(self.eat_keyword(keywords::Move) ){
Expand Down