Skip to content

Commit

Permalink
Auto merge of #26002 - Manishearth:rollup, r=Manishearth
Browse files Browse the repository at this point in the history
- Successful merges: #25900, #25987, #25988, #25990, #25994, #26000
- Failed merges:
  • Loading branch information
bors committed Jun 4, 2015
2 parents 80d08a3 + fd3b6ca commit 0aeb9f6
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 12 deletions.
2 changes: 1 addition & 1 deletion AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ Hajime Morrita <omo@dodgson.org>
Hanno Braun <mail@hannobraun.de>
Harry Marr <harry.marr@gmail.com>
Heather <heather@cynede.net>
Heejong Ahn <heejongahn@gmail.com
Heejong Ahn <heejongahn@gmail.com>
Henrik Schopmans <h.schopmans@googlemail.com>
Herman J. Radtke III <herman@hermanradtke.com>
HeroesGrave <heroesgrave@gmail.com>
Expand Down
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

0 comments on commit 0aeb9f6

Please sign in to comment.