Merge branch 'master' into mulit-decor

This commit is contained in:
Nick Cameron 2015-05-13 15:09:17 +12:00
commit 103e52b1db
85 changed files with 2390 additions and 889 deletions

View file

@ -253,7 +253,7 @@ The two values of the boolean type are written `true` and `false`.
### Symbols
```antlr
symbol : "::" "->"
symbol : "::" | "->"
| '#' | '[' | ']' | '(' | ')' | '{' | '}'
| ',' | ';' ;
```
@ -304,7 +304,7 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']'
## Items
```antlr
item : mod_item | fn_item | type_item | struct_item | enum_item
item : vis ? mod_item | fn_item | type_item | struct_item | enum_item
| const_item | static_item | trait_item | impl_item | extern_block ;
```
@ -322,7 +322,7 @@ mod : [ view_item | item ] * ;
#### View items
```antlr
view_item : extern_crate_decl | use_decl ;
view_item : extern_crate_decl | use_decl ';' ;
```
##### Extern crate declarations
@ -335,14 +335,14 @@ crate_name: ident | ( ident "as" ident )
##### Use declarations
```antlr
use_decl : "pub" ? "use" [ path "as" ident
| path_glob ] ;
use_decl : vis ? "use" [ path "as" ident
| path_glob ] ;
path_glob : ident [ "::" [ path_glob
| '*' ] ] ?
| '{' path_item [ ',' path_item ] * '}' ;
path_item : ident | "mod" ;
path_item : ident | "self" ;
```
### Functions
@ -414,16 +414,17 @@ extern_block : [ foreign_fn ] * ;
## Visibility and Privacy
**FIXME:** grammar?
```antlr
vis : "pub" ;
```
### Re-exporting and Visibility
**FIXME:** grammar?
See [Use declarations](#use-declarations).
## Attributes
```antlr
attribute : "#!" ? '[' meta_item ']' ;
attribute : '#' '!' ? '[' meta_item ']' ;
meta_item : ident [ '=' literal
| '(' meta_seq ')' ] ? ;
meta_seq : meta_item [ ',' meta_seq ] ? ;
@ -433,26 +434,19 @@ meta_seq : meta_item [ ',' meta_seq ] ? ;
## Statements
**FIXME:** grammar?
```antlr
stmt : decl_stmt | expr_stmt ;
```
### Declaration statements
**FIXME:** grammar?
A _declaration statement_ is one that introduces one or more *names* into the
enclosing statement block. The declared names may denote new variables or new
items.
```antlr
decl_stmt : item | let_decl ;
```
#### Item declarations
**FIXME:** grammar?
An _item declaration statement_ has a syntactic form identical to an
[item](#items) declaration within a module. Declaring an item — a
function, enumeration, structure, type, static, trait, implementation or module
— locally within a statement block is simply a way of restricting its
scope to a narrow region containing all of its uses; it is otherwise identical
in meaning to declaring the item outside the statement block.
See [Items](#items).
#### Variable declarations
@ -463,11 +457,21 @@ init : [ '=' ] expr ;
### Expression statements
**FIXME:** grammar?
```antlr
expr_stmt : expr ';' ;
```
## Expressions
**FIXME:** grammar?
```antlr
expr : literal | path | tuple_expr | unit_expr | struct_expr
| block_expr | method_call_expr | field_expr | array_expr
| idx_expr | range_expr | unop_expr | binop_expr
| paren_expr | call_expr | lambda_expr | while_expr
| loop_expr | break_expr | continue_expr | for_expr
| if_expr | match_expr | if_let_expr | while_let_expr
| return_expr ;
```
#### Lvalues, rvalues and temporaries
@ -479,19 +483,23 @@ init : [ '=' ] expr ;
### Literal expressions
**FIXME:** grammar?
See [Literals](#literals).
### Path expressions
**FIXME:** grammar?
See [Paths](#paths).
### Tuple expressions
**FIXME:** grammar?
```antlr
tuple_expr : '(' [ expr [ ',' expr ] * | expr ',' ] ? ')' ;
```
### Unit expressions
**FIXME:** grammar?
```antlr
unit_expr : "()" ;
```
### Structure expressions
@ -507,8 +515,7 @@ struct_expr : expr_path '{' ident ':' expr
### Block expressions
```antlr
block_expr : '{' [ view_item ] *
[ stmt ';' | item ] *
block_expr : '{' [ stmt ';' | item ] *
[ expr ] '}' ;
```
@ -529,7 +536,7 @@ field_expr : expr '.' ident ;
```antlr
array_expr : '[' "mut" ? array_elems? ']' ;
array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ;
array_elems : [expr [',' expr]*] | [expr ';' expr] ;
```
### Index expressions
@ -549,66 +556,61 @@ range_expr : expr ".." expr |
### Unary operator expressions
**FIXME:** grammar?
```antlr
unop_expr : unop expr ;
unop : '-' | '*' | '!' ;
```
### Binary operator expressions
```antlr
binop_expr : expr binop expr ;
binop_expr : expr binop expr | type_cast_expr
| assignment_expr | compound_assignment_expr ;
binop : arith_op | bitwise_op | lazy_bool_op | comp_op
```
#### Arithmetic operators
**FIXME:** grammar?
```antlr
arith_op : '+' | '-' | '*' | '/' | '%' ;
```
#### Bitwise operators
**FIXME:** grammar?
```antlr
bitwise_op : '&' | '|' | '^' | "<<" | ">>" ;
```
#### Lazy boolean operators
**FIXME:** grammar?
```antlr
lazy_bool_op : "&&" | "||" ;
```
#### Comparison operators
**FIXME:** grammar?
```antlr
comp_op : "==" | "!=" | '<' | '>' | "<=" | ">=" ;
```
#### Type cast expressions
**FIXME:** grammar?
```antlr
type_cast_expr : value "as" type ;
```
#### Assignment expressions
**FIXME:** grammar?
```antlr
assignment_expr : expr '=' expr ;
```
#### Compound assignment expressions
**FIXME:** grammar?
#### Operator precedence
The precedence of Rust binary operators is ordered as follows, going from
strong to weak:
```text
* / %
as
+ -
<< >>
&
^
|
< > <= >=
== !=
&&
||
=
```antlr
compound_assignment_expr : expr [ arith_op | bitwise_op ] '=' expr ;
```
Operators at the same precedence level are evaluated left-to-right. [Unary
operators](#unary-operator-expressions) have the same precedence level and it
is stronger than any of the binary operators'.
### Grouped expressions
```antlr

View file

@ -5,15 +5,14 @@ to jump to any particular section.
# Getting Started
If you haven't seen Rust at all yet, the first thing you should read is the [30
minute intro](intro.html). It will give you an overview of the basic ideas of Rust
at a high level.
If you haven't seen Rust at all yet, the first thing you should read is the
introduction to [The Rust Programming Language](book/index.html). It'll give
you a good idea of what Rust is like.
Once you know you really want to learn Rust, the next step is reading [The
Rust Programming Language](book/index.html). It is a lengthy explanation of
Rust, its syntax, and its concepts. Upon completing the book, you'll be an
intermediate Rust developer, and will have a good grasp of the fundamental
ideas behind Rust.
The book provides a lengthy explanation of Rust, its syntax, and its
concepts. Upon completing the book, you'll be an intermediate Rust
developer, and will have a good grasp of the fundamental ideas behind
Rust.
[Rust By Example][rbe] was originally a community resource, but was then
donated to the Rust project. As the name implies, it teaches you Rust through a
@ -24,7 +23,7 @@ series of small examples.
# Community & Getting Help
If you need help with something, or just want to talk about Rust with others,
there's a few places you can do that:
there are a few places you can do that:
The Rust IRC channels on [irc.mozilla.org](http://irc.mozilla.org/) are the
fastest way to get help.
@ -59,7 +58,7 @@ the language in as much detail as possible is in [the reference](reference.html)
# Tools
Rust's still a young language, so there isn't a ton of tooling yet, but the
Rust is still a young language, so there isn't a ton of tooling yet, but the
tools we have are really nice.
[Cargo](http://crates.io) is Rust's package manager, and its website contains
@ -69,16 +68,21 @@ lots of good documentation.
# FAQs
There are questions that are asked quite often, and so we've made FAQs for them:
There are questions that are asked quite often, so we've made FAQs for them:
* [Language Design FAQ](complement-design-faq.html)
* [Language FAQ](complement-lang-faq.html)
* [Project FAQ](complement-project-faq.html)
* [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports)
# The standard library
# The Standard Library
We have [API documentation for the entire standard
library](std/index.html). There's a list of crates on the left with more
specific sections, or you can use the search bar at the top to search for
something if you know its name.
# The Error Index
If you encounter an error while compiling your code you may be able to look it
up in the [Rust Compiler Error Index](error-index.html).

View file

@ -31,23 +31,27 @@ You may also be interested in the [grammar].
## Unicode productions
A few productions in Rust's grammar permit Unicode code points outside the ASCII
range. We define these productions in terms of character properties specified
in the Unicode standard, rather than in terms of ASCII-range code points. The
section [Special Unicode Productions](#special-unicode-productions) lists these
productions.
A few productions in Rust's grammar permit Unicode code points outside the
ASCII range. We define these productions in terms of character properties
specified in the Unicode standard, rather than in terms of ASCII-range code
points. The grammar has a [Special Unicode Productions][unicodeproductions]
section that lists these productions.
[unicodeproductions]: grammar.html#special-unicode-productions
## String table productions
Some rules in the grammar &mdash; notably [unary
operators](#unary-operator-expressions), [binary
operators](#binary-operator-expressions), and [keywords](#keywords) &mdash; are
operators](#binary-operator-expressions), and [keywords][keywords] &mdash; are
given in a simplified form: as a listing of a table of unquoted, printable
whitespace-separated strings. These cases form a subset of the rules regarding
the [token](#tokens) rule, and are assumed to be the result of a
lexical-analysis phase feeding the parser, driven by a DFA, operating over the
disjunction of all such string table entries.
[keywords]: grammar.html#keywords
When such a string enclosed in double-quotes (`"`) occurs inside the grammar,
it is an implicit reference to a single member of such a string table
production. See [tokens](#tokens) for more information.
@ -75,7 +79,7 @@ An identifier is any nonempty Unicode[^non_ascii_idents] string of the following
- The first character has property `XID_start`
- The remaining characters have property `XID_continue`
that does _not_ occur in the set of [keywords](#keywords).
that does _not_ occur in the set of [keywords][keywords].
> **Note**: `XID_start` and `XID_continue` as character properties cover the
> character ranges used to form the more familiar C and Java language-family
@ -401,7 +405,7 @@ Symbols are a general class of printable [token](#tokens) that play structural
roles in a variety of grammar productions. They are catalogued here for
completeness as the set of remaining miscellaneous printable tokens that do not
otherwise appear as [unary operators](#unary-operator-expressions), [binary
operators](#binary-operator-expressions), or [keywords](#keywords).
operators](#binary-operator-expressions), or [keywords][keywords].
## Paths
@ -422,12 +426,12 @@ x;
x::y::z;
```
Path components are usually [identifiers](#identifiers), but the trailing
component of a path may be an angle-bracket-enclosed list of type arguments. In
[expression](#expressions) context, the type argument list is given after a
final (`::`) namespace qualifier in order to disambiguate it from a relational
expression involving the less-than symbol (`<`). In type expression context,
the final namespace qualifier is omitted.
Path components are usually [identifiers](#identifiers), but they may
also include angle-bracket-enclosed lists of type arguments. In
[expression](#expressions) context, the type argument list is given
after a `::` namespace qualifier in order to disambiguate it from a
relational expression involving the less-than symbol (`<`). In type
expression context, the final namespace qualifier is omitted.
Two examples of paths with type arguments:
@ -493,8 +497,9 @@ names, and invoked through a consistent syntax: `some_extension!(...)`.
Users of `rustc` can define new syntax extensions in two ways:
* [Compiler plugins][plugin] can include arbitrary
Rust code that manipulates syntax trees at compile time.
* [Compiler plugins][plugin] can include arbitrary Rust code that
manipulates syntax trees at compile time. Note that the interface
for compiler plugins is considered highly unstable.
* [Macros](book/macros.html) define new syntax in a higher-level,
declarative way.
@ -547,7 +552,7 @@ _name_ s that occur in its body. At the "current layer", they all must repeat
the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $(
($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but not
`(a,b,c ; d,e)`. The repetition walks through the choices at that layer in
lockstep, so the former input transcribes to `( (a,d), (b,e), (c,f) )`.
lockstep, so the former input transcribes to `(a,d), (b,e), (c,f)`.
Nested repetitions are allowed.
@ -556,14 +561,18 @@ Nested repetitions are allowed.
The parser used by the macro system is reasonably powerful, but the parsing of
Rust syntax is restricted in two ways:
1. The parser will always parse as much as possible. If it attempts to match
`$i:expr [ , ]` against `8 [ , ]`, it will attempt to parse `i` as an array
index operation and fail. Adding a separator can solve this problem.
1. Macro definitions are required to include suitable separators after parsing
expressions and other bits of the Rust grammar. This implies that
a macro definition like `$i:expr [ , ]` is not legal, because `[` could be part
of an expression. A macro definition like `$i:expr,` or `$i:expr;` would be legal,
however, because `,` and `;` are legal separators. See [RFC 550] for more information.
2. The parser must have eliminated all ambiguity by the time it reaches a `$`
_name_ `:` _designator_. This requirement most often affects name-designator
pairs when they occur at the beginning of, or immediately after, a `$(...)*`;
requiring a distinctive token in front can solve the problem.
[RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md
# Crates and source files
Although Rust, like any other language, can be implemented by an interpreter as
@ -611,7 +620,7 @@ module needs its own source file: [module definitions](#modules) can be nested
within one file.
Each source file contains a sequence of zero or more `item` definitions, and
may optionally begin with any number of [attributes](#Items and attributes)
may optionally begin with any number of [attributes](#items-and-attributes)
that apply to the containing module, most of which influence the behavior of
the compiler. The anonymous crate module can have additional attributes that
apply to the crate as a whole.
@ -653,9 +662,10 @@ There are several kinds of item:
* [`use` declarations](#use-declarations)
* [modules](#modules)
* [functions](#functions)
* [type definitions](#type-definitions)
* [type definitions](grammar.html#type-definitions)
* [structures](#structures)
* [enumerations](#enumerations)
* [constant items](#constant-items)
* [static items](#static-items)
* [traits](#traits)
* [implementations](#implementations)
@ -672,16 +682,17 @@ which sub-item declarations may appear.
### Type Parameters
All items except modules may be *parameterized* by type. Type parameters are
given as a comma-separated list of identifiers enclosed in angle brackets
(`<...>`), after the name of the item and before its definition. The type
parameters of an item are considered "part of the name", not part of the type
of the item. A referencing [path](#paths) must (in principle) provide type
arguments as a list of comma-separated types enclosed within angle brackets, in
order to refer to the type-parameterized item. In practice, the type-inference
system can usually infer such argument types from context. There are no
general type-parametric types, only type-parametric items. That is, Rust has
no notion of type abstraction: there are no first-class "forall" types.
All items except modules, constants and statics may be *parameterized* by type.
Type parameters are given as a comma-separated list of identifiers enclosed in
angle brackets (`<...>`), after the name of the item and before its definition.
The type parameters of an item are considered "part of the name", not part of
the type of the item. A referencing [path](#paths) must (in principle) provide
type arguments as a list of comma-separated types enclosed within angle
brackets, in order to refer to the type-parameterized item. In practice, the
type-inference system can usually infer such argument types from context. There
are no general type-parametric types, only type-parametric items. That is, Rust
has no notion of type abstraction: there are no higher-ranked (or "forall") types
abstracted over other types, though higher-ranked types do exist for lifetimes.
### Modules
@ -727,6 +738,7 @@ mod vec;
mod thread {
// Load the `local_data` module from `thread/local_data.rs`
// or `thread/local_data/mod.rs`.
mod local_data;
}
```
@ -743,7 +755,7 @@ mod thread {
}
```
##### Extern crate declarations
#### Extern crate declarations
An _`extern crate` declaration_ specifies a dependency on an external crate.
The external crate is then bound into the declaring scope as the `ident`
@ -767,12 +779,12 @@ extern crate std; // equivalent to: extern crate std as std;
extern crate std as ruststd; // linking to 'std' under another name
```
##### Use declarations
#### Use declarations
A _use declaration_ creates one or more local name bindings synonymous with
some other [path](#paths). Usually a `use` declaration is used to shorten the
path required to refer to a module item. These declarations may appear at the
top of [modules](#modules) and [blocks](#blocks).
top of [modules](#modules) and [blocks](grammar.html#block-expressions).
> **Note**: Unlike in many languages,
> `use` declarations in Rust do *not* declare linkage dependency with external crates.
@ -842,7 +854,7 @@ module declarations should be at the crate root if direct usage of the declared
modules within `use` items is desired. It is also possible to use `self` and
`super` at the beginning of a `use` item to refer to the current and direct
parent modules respectively. All rules regarding accessing declared modules in
`use` declarations applies to both module declarations and `extern crate`
`use` declarations apply to both module declarations and `extern crate`
declarations.
An example of what will and will not work for `use` items:
@ -999,7 +1011,8 @@ the guarantee that these issues are never caused by safe code.
* `&mut` and `&` follow LLVMs scoped [noalias] model, except if the `&T`
contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
guarantees.
* Mutating an immutable value/reference without `UnsafeCell<U>`
* Mutating non-mutable data (that is, data reached through a shared reference or
data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
* Invoking undefined behavior via compiler intrinsics:
* Indexing outside of the bounds of an object with `std::ptr::offset`
(`offset` intrinsic), with
@ -1029,9 +1042,13 @@ be undesired.
* Exiting without calling destructors
* Sending signals
* Accessing/modifying the file system
* Unsigned integer overflow (well-defined as wrapping)
* Signed integer overflow (well-defined as twos complement representation
wrapping)
* Integer overflow
- Overflow is considered "unexpected" behavior and is always user-error,
unless the `wrapping` primitives are used. In non-optimized builds, the compiler
will insert debug checks that panic on overflow, but in optimized builds overflow
instead results in wrapped values. See [RFC 560] for the rationale and more details.
[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
#### Diverging functions
@ -1143,9 +1160,7 @@ let px: i32 = match p { Point(x, _) => x };
```
A _unit-like struct_ is a structure without any fields, defined by leaving off
the list of fields entirely. Such types will have a single value, just like
the [unit value `()`](#unit-and-boolean-literals) of the unit type. For
example:
the list of fields entirely. Such types will have a single value. For example:
```
struct Cookie;
@ -1307,11 +1322,26 @@ type of the value is not required to ascribe to `Sync`.
### Traits
A _trait_ describes a set of method types.
A _trait_ describes an abstract interface that types can
implement. This interface consists of associated items, which come in
three varieties:
Traits can include default implementations of methods, written in terms of some
unknown [`self` type](#self-types); the `self` type may either be completely
unspecified, or constrained by some other trait.
- functions
- constants
- types
Associated functions whose first parameter is named `self` are called
methods and may be invoked using `.` notation (e.g., `x.foo()`).
All traits define an implicit type parameter `Self` that refers to
"the type that is implementing this interface". Traits may also
contain additional type parameters. These type parameters (including
`Self`) may be constrained by other traits and so forth as usual.
Trait bounds on `Self` are considered "supertraits". These are
required to be acyclic. Supertraits are somewhat different from other
constraints in that they affect what methods are available in the
vtable when the trait is used as a [trait object](#trait-objects).
Traits are implemented for specific types through separate
[implementations](#implementations).
@ -1356,15 +1386,18 @@ fn draw_twice<T: Shape>(surface: Surface, sh: T) {
}
```
Traits also define an [trait object](#trait-objects) with the same name as the
trait. Values of this type are created by [casting](#type-cast-expressions)
pointer values (pointing to a type for which an implementation of the given
trait is in scope) to pointers to the trait name, used as a type.
Traits also define an [trait object](#trait-objects) with the same
name as the trait. Values of this type are created by coercing from a
pointer of some specific type to a pointer of trait type. For example,
`&T` could be coerced to `&Shape` if `T: Shape` holds (and similarly
for `Box<T>`). This coercion can either be implicit or
[explicit](#type-cast-expressions). Here is an example of an explicit
coercion:
```
# trait Shape { fn dummy(&self) { } }
# impl Shape for i32 { }
# let mycircle = 0i32;
trait Shape { }
impl Shape for i32 { }
let mycircle = 0i32;
let myshape: Box<Shape> = Box::new(mycircle) as Box<Shape>;
```
@ -2038,7 +2071,8 @@ The name `str_eq` has a special meaning to the Rust compiler, and the presence
of this definition means that it will use this definition when generating calls
to the string equality function.
A complete list of the built-in language items will be added in the future.
The set of language items is currently considered unstable. A complete
list of the built-in language items will be added in the future.
### Inline attributes
@ -2050,11 +2084,6 @@ The compiler automatically inlines functions based on internal heuristics.
Incorrectly inlining functions can actually make the program slower, so it
should be used with care.
Immutable statics are always considered inlineable unless marked with
`#[inline(never)]`. It is undefined whether two different inlineable statics
have the same memory address. In other words, the compiler is free to collapse
duplicate inlineable statics together.
`#[inline]` and `#[inline(always)]` always cause the function to be serialized
into the crate metadata to allow cross-crate inlining.
@ -2256,10 +2285,6 @@ The currently implemented features of the reference compiler are:
* `unboxed_closures` - Rust's new closure design, which is currently a work in
progress feature with many known bugs.
* `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute,
which is considered wildly unsafe and will be
obsoleted by language improvements.
* `unsafe_no_drop_flag` - Allows use of the `#[unsafe_no_drop_flag]` attribute,
which removes hidden flag added to a type that
implements the `Drop` trait. The design for the
@ -2379,18 +2404,54 @@ expressions](#index-expressions) (`expr[expr]`), and [field
references](#field-expressions) (`expr.f`). All other expressions are rvalues.
The left operand of an [assignment](#assignment-expressions) or
[compound-assignment](#compound-assignment-expressions) expression is an lvalue
context, as is the single operand of a unary
[borrow](#unary-operator-expressions). All other expression contexts are
rvalue contexts.
[compound-assignment](#compound-assignment-expressions) expression is
an lvalue context, as is the single operand of a unary
[borrow](#unary-operator-expressions). The discriminant or subject of
a [match expression](#match-expressions) may be an lvalue context, if
ref bindings are made, but is otherwise an rvalue context. All other
expression contexts are rvalue contexts.
When an lvalue is evaluated in an _lvalue context_, it denotes a memory
location; when evaluated in an _rvalue context_, it denotes the value held _in_
that memory location.
When an rvalue is used in an lvalue context, a temporary un-named lvalue is
created and used instead. A temporary's lifetime equals the largest lifetime
of any reference that points to it.
##### Temporary lifetimes
When an rvalue is used in an lvalue context, a temporary un-named
lvalue is created and used instead. The lifetime of temporary values
is typically the innermost enclosing statement; the tail expression of
a block is considered part of the statement that encloses the block.
When a temporary rvalue is being created that is assigned into a `let`
declaration, however, the temporary is created with the lifetime of
the enclosing block instead, as using the enclosing statement (the
`let` declaration) would be a guaranteed error (since a pointer to the
temporary would be stored into a variable, but the temporary would be
freed before the variable could be used). The compiler uses simple
syntactic rules to decide which values are being assigned into a `let`
binding, and therefore deserve a longer temporary lifetime.
Here are some examples:
- `let x = foo(&temp())`. The expression `temp()` is an rvalue. As it
is being borrowed, a temporary is created which will be freed after
the innermost enclosing statement (the `let` declaration, in this case).
- `let x = temp().foo()`. This is the same as the previous example,
except that the value of `temp()` is being borrowed via autoref on a
method-call. Here we are assuming that `foo()` is an `&self` method
defined in some trait, say `Foo`. In other words, the expression
`temp().foo()` is equivalent to `Foo::foo(&temp())`.
- `let x = &temp()`. Here, the same temporary is being assigned into
`x`, rather than being passed as a parameter, and hence the
temporary's lifetime is considered to be the enclosing block.
- `let x = SomeStruct { foo: &temp() }`. As in the previous case, the
temporary is assigned into a struct which is then assigned into a
binding, and hence it is given the lifetime of the enclosing block.
- `let x = [ &temp() ]`. As in the previous case, the
temporary is assigned into an array which is then assigned into a
binding, and hence it is given the lifetime of the enclosing block.
- `let ref x = temp()`. In this case, the temporary is created using a ref binding,
but the result is the same: the lifetime is extended to the enclosing block.
#### Moved and copied types
@ -2435,11 +2496,6 @@ comma:
(0); // zero in parentheses
```
### Unit expressions
The expression `()` denotes the _unit value_, the only value of the type with
the same name.
### Structure expressions
There are several forms of structure expressions. A _structure expression_
@ -2537,8 +2593,10 @@ A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to
the value of that field. When the type providing the field inherits mutability,
it can be [assigned](#assignment-expressions) to.
Also, if the type of the expression to the left of the dot is a pointer, it is
automatically dereferenced to make the field access possible.
Also, if the type of the expression to the left of the dot is a
pointer, it is automatically dereferenced as many times as necessary
to make the field access possible. In cases of ambiguity, we prefer
fewer autoderefs to more.
### Array expressions
@ -2564,14 +2622,26 @@ array is mutable, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can
be assigned to.
Indices are zero-based, and may be of any integral type. Vector access is
bounds-checked at run-time. When the check fails, it will put the thread in a
_panicked state_.
bounds-checked at compile-time for constant arrays being accessed with a constant index value.
Otherwise a check will be performed at run-time that will put the thread in a _panicked state_ if it fails.
```{should-fail}
([1, 2, 3, 4])[0];
(["a", "b"])[10]; // panics
let x = (["a", "b"])[10]; // compiler error: const index-expr is out of bounds
let n = 10;
let y = (["a", "b"])[n]; // panics
let arr = ["a", "b"];
arr[10]; // panics
```
Also, if the type of the expression to the left of the brackets is a
pointer, it is automatically dereferenced as many times as necessary
to make the indexing possible. In cases of ambiguity, we prefer fewer
autoderefs to more.
### Range expressions
The `..` operator will construct an object of one of the `std::ops::Range` variants.
@ -2594,7 +2664,7 @@ assert_eq!(x,y);
### Unary operator expressions
Rust defines three unary operators. They are all written as prefix operators,
Rust defines the following unary operators. They are all written as prefix operators,
before the expression they apply to.
* `-`
@ -2608,11 +2678,20 @@ before the expression they apply to.
implemented by the type and required for an outer expression that will or
could mutate the dereference), and produces the result of dereferencing the
`&` or `&mut` borrowed pointer returned from the overload method.
* `!`
: Logical negation. On the boolean type, this flips between `true` and
`false`. On integer types, this inverts the individual bits in the
two's complement representation of the value.
* `&` and `&mut`
: Borrowing. When applied to an lvalue, these operators produce a
reference (pointer) to the lvalue. The lvalue is also placed into
a borrowed state for the duration of the reference. For a shared
borrow (`&`), this implies that the lvalue may not be mutated, but
it may be read or shared again. For a mutable borrow (`&mut`), the
lvalue may not be accessed in any way until the borrow expires.
If the `&` or `&mut` operators are applied to an rvalue, a
temporary value is created; the lifetime of this temporary value
is defined by [syntactic rules](#temporary-lifetimes).
### Binary operator expressions
@ -2722,6 +2801,13 @@ fn avg(v: &[f64]) -> f64 {
}
```
Some of the conversions which can be done through the `as` operator
can also be done implicitly at various points in the program, such as
argument passing and assignment to a `let` binding with an explicit
type. Implicit conversions are limited to "harmless" conversions that
do not lose information and which have minimal or no risk of
surprising side-effects on the dynamic execution semantics.
#### Assignment expressions
An _assignment expression_ consists of an
@ -3064,6 +3150,20 @@ of a condition expression it expects a refutable let statement. If the value of
expression on the right hand side of the let statement matches the pattern, the corresponding
block will execute, otherwise flow proceeds to the first `else` block that follows.
```
let dish = ("Ham", "Eggs");
// this body will be skipped because the pattern is refuted
if let ("Bacon", b) = dish {
println!("Bacon is served with {}", b);
}
// this body will execute
if let ("Ham", b) = dish {
println!("Ham is served with {}", b);
}
```
### While let loops
A `while let` loop is semantically identical to a `while` loop but in place of a
@ -3259,7 +3359,7 @@ constructor or `struct` field may refer, directly or indirectly, to the
enclosing `enum` or `struct` type itself. Such recursion has restrictions:
* Recursive types must include a nominal type in the recursion
(not mere [type definitions](#type-definitions),
(not mere [type definitions](grammar.html#type-definitions),
or other structural types such as [arrays](#array,-and-slice-types) or [tuples](#tuple-types)).
* A recursive `enum` item must have at least one non-recursive constructor
(in order to give the recursion a basis case).
@ -3329,6 +3429,22 @@ let bo: Binop = add;
x = bo(5,7);
```
#### Function types for specific items
Internally to the compiler, there are also function types that are specific to a particular
function item. In the following snippet, for example, the internal types of the functions
`foo` and `bar` are different, despite the fact that they have the same signature:
```
fn foo() { }
fn bar() { }
```
The types of `foo` and `bar` can both be implicitly coerced to the fn
pointer type `fn()`. There is currently no syntax for unique fn types,
though the compiler will emit a type like `fn() {foo}` in error
messages to indicate "the unique fn type for the function `foo`".
### Closure types
A [lambda expression](#lambda-expressions) produces a closure value with
@ -3413,8 +3529,9 @@ has type `Vec<A>`, a vector with element type `A`.
### Self types
The special type `self` has a meaning within methods inside an impl item. It
refers to the type of the implicit `self` argument. For example, in:
The special type `Self` has a meaning within traits and impls. In a trait definition, it refers
to an implicit type parameter representing the "implementing" type. In an impl,
it is an alias for the implementing type. For example, in:
```
trait Printable {
@ -3428,8 +3545,9 @@ impl Printable for String {
}
```
`self` refers to the value of type `String` that is the receiver for a call to
the method `make_string`.
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`.
# Special traits

View file

@ -15,6 +15,7 @@
* [Concurrency](concurrency.md)
* [Error Handling](error-handling.md)
* [FFI](ffi.md)
* [Borrow and AsRef](borrow-and-asref.md)
* [Syntax and Semantics](syntax-and-semantics.md)
* [Variable Bindings](variable-bindings.md)
* [Functions](functions.md)

View file

@ -0,0 +1,93 @@
% Borrow and AsRef
The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but
different. Heres a quick refresher on what these two traits mean.
[borrow]: ../std/borrow/trait.Borrow.html
[asref]: ../std/convert/trait.AsRef.html
# Borrow
The `Borrow` trait is used when youre writing a datastructure, and you want to
use either an owned or borrowed type as synonymous for some purpose.
For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`:
```rust,ignore
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Hash + Eq
```
[hashmap]: ../std/collections/struct.HashMap.html
[get]: ../std/collections/struct.HashMap.html#method.get
This signature is pretty complicated. The `K` parameter is what were interested
in here. It refers to a parameter of the `HashMap` itself:
```rust,ignore
struct HashMap<K, V, S = RandomState> {
```
The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at
the signature of `get()` again, we can use `get()` when the key implements
`Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys,
but use `&str`s when were searching:
```rust
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("Foo".to_string(), 42);
assert_eq!(map.get("Foo"), Some(&42));
```
This is because the standard library has `impl Borrow<str> for String`.
For most types, when you want to take an owned or borrowed type, a `&T` is
enough. But one area where `Borrow` is effective is when theres more than one
kind of borrowed value. Slices are an area where this is especially true: you
can have both an `&[T]` or a `&mut [T]`. If we wanted to accept both of these
types, `Borrow` is up for it:
```
use std::borrow::Borrow;
use std::fmt::Display;
fn foo<T: Borrow<i32> + Display>(a: T) {
println!("a is borrowed: {}", a);
}
let mut i = 5;
foo(&i);
foo(&mut i);
```
This will print out `a is borrowed: 5` twice.
# AsRef
The `AsRef` trait is a conversion trait. Its used for converting some value to
a reference in generic code. Like this:
```rust
let s = "Hello".to_string();
fn foo<T: AsRef<str>>(s: T) {
let slice = s.as_ref();
}
```
# Which should I use?
We can see how theyre kind of the same: they both deal with owned and borrowed
versions of some type. However, theyre a bit different.
Choose `Borrow` when you want to abstract over different kinds of borrowing, or
when youre building a datastructure that treats owned and borrowed values in
equivalent ways, such as hashing and comparison.
Choose `AsRef` when you want to convert something to a reference directly, and
youre writing generic code.

View file

@ -176,7 +176,7 @@ for a full example, the core of which is reproduced here:
```ignore
declare_lint!(TEST_LINT, Warn,
"Warn about items named 'lintme'")
"Warn about items named 'lintme'");
struct Pass;

View file

@ -273,7 +273,7 @@ information. Why throw it away? Well, for a basic program, we just want to
print a generic error, as basically any issue means we cant continue. The
[`ok()` method][ok] returns a value which has another method defined on it:
`expect()`. The [`expect()` method][expect] takes a value its called on, and
if it isnt a successful one, [`panic!`][panic]s with a message you passed you
if it isnt a successful one, [`panic!`][panic]s with a message you
passed it. A `panic!` like this will cause our program to crash, displaying
the message.
@ -713,7 +713,7 @@ variety of numbers, we need to give Rust a hint as to the exact type of number
we want. Hence, `let guess: u32`. The colon (`:`) after `guess` tells Rust
were going to annotate its type. `u32` is an unsigned, thirty-two bit
integer. Rust has [a number of built-in number types][number], but weve
chosen `u32`. Its a good default choice for a small positive numer.
chosen `u32`. Its a good default choice for a small positive number.
[parse]: ../std/primitive.str.html#method.parse
[number]: primitive-types.html#numeric-types
@ -922,7 +922,7 @@ failure. Each contains more information: the successful parsed integer, or an
error type. In this case, we `match` on `Ok(num)`, which sets the inner value
of the `Ok` to the name `num`, and then we just return it on the right-hand
side. In the `Err` case, we dont care what kind of error it is, so we just
use `_` intead of a name. This ignores the error, and `continue` causes us
use `_` instead of a name. This ignores the error, and `continue` causes us
to go to the next iteration of the `loop`.
Now we should be good! Lets try:

View file

@ -5,7 +5,7 @@ Rusts most unique and compelling features, with which Rust developers should
become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own chapter:
* [ownership][ownership], ownership, the key concept
* [ownership][ownership], the key concept
* [borrowing][borrowing], and their associated feature references
* lifetimes, which youre reading now

View file

@ -50,7 +50,7 @@ side of a `let` binding or directly where an expression is used:
```rust
let x = 5;
let numer = match x {
let number = match x {
1 => "one",
2 => "two",
3 => "three",

View file

@ -127,12 +127,12 @@ fn grow(&self) -> Circle {
We just say were returning a `Circle`. With this method, we can grow a new
circle to any arbitrary size.
# Static methods
# Associated functions
You can also define static methods that do not take a `self` parameter. Heres a
pattern thats very common in Rust code:
You can also define associated functions that do not take a `self` parameter.
Heres a pattern thats very common in Rust code:
```
```rust
struct Circle {
x: f64,
y: f64,

View file

@ -78,8 +78,8 @@ When we call `clone()`, the `Arc<T>` needs to update the reference count. Yet
weve not used any `mut`s here, `x` is an immutable binding, and we didnt take
`&mut 5` or anything. So what gives?
To this, we have to go back to the core of Rusts guiding philosophy, memory
safety, and the mechanism by which Rust guarantees it, the
To understand this, we have to go back to the core of Rusts guiding
philosophy, memory safety, and the mechanism by which Rust guarantees it, the
[ownership][ownership] system, and more specifically, [borrowing][borrowing]:
> You may have one or the other of these two kinds of borrows, but not both at
@ -169,7 +169,7 @@ struct Point {
y: Cell<i32>,
}
let mut point = Point { x: 5, y: Cell::new(6) };
let point = Point { x: 5, y: Cell::new(6) };
point.y.set(7);

View file

@ -6,7 +6,7 @@ become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own
chapter:
* ownership, which youre reading now.
* ownership, which youre reading now
* [borrowing][borrowing], and their associated feature references
* [lifetimes][lifetimes], an advanced concept of borrowing
@ -23,7 +23,7 @@ Before we get to the details, two important notes about the ownership system.
Rust has a focus on safety and speed. It accomplishes these goals through many
zero-cost abstractions, which means that in Rust, abstractions cost as little
as possible in order to make them work. The ownership system is a prime example
of a zero cost abstraction. All of the analysis well talk about in this guide
of a zero-cost abstraction. All of the analysis well talk about in this guide
is _done at compile time_. You do not pay any run-time cost for any of these
features.
@ -41,7 +41,7 @@ With that in mind, lets learn about ownership.
# Ownership
[`Variable bindings`][bindings] have a property in Rust: they have ownership
[Variable bindings][bindings] have a property in Rust: they have ownership
of what theyre bound to. This means that when a binding goes out of scope, the
resource that theyre bound to are freed. For example:
@ -106,8 +106,8 @@ take(v);
println!("v[0] is: {}", v[0]);
```
Same error: “use of moved value.” When we transfer ownership to something else,
we say that weve moved the thing we refer to. You dont need some sort of
Same error: use of moved value. When we transfer ownership to something else,
we say that weve moved the thing we refer to. You dont need any sort of
special annotation here, its the default thing that Rust does.
## The details
@ -121,19 +121,19 @@ let v = vec![1, 2, 3];
let v2 = v;
```
The first line creates some data for the vector on the [stack][sh], `v`. The
vectors data, however, is stored on the [heap][sh], and so it contains a
pointer to that data. When we move `v` to `v2`, it creates a copy of that pointer,
for `v2`. Which would mean two pointers to the contents of the vector on the
heap. That would be a problem: it would violate Rusts safety guarantees by
introducing a data race. Therefore, Rust forbids using `v` after weve done the
move.
The first line allocates memory for the vector object, `v`, and for the data it
contains. The vector object is stored on the [stack][sh] and contains a pointer
to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`,
it creates a copy of that pointer, for `v2`. Which means that there would be two
pointers to the content of the vector on the heap. It would violate Rusts
safety guarantees by introducing a data race. Therefore, Rust forbids using `v`
after weve done the move.
[sh]: the-stack-and-the-heap.html
Its also important to note that optimizations may remove the actual copy of
the bytes, depending on circumstances. So it may not be as inefficient as it
initially seems.
the bytes on the stack, depending on circumstances. So it may not be as
inefficient as it initially seems.
## `Copy` types
@ -174,7 +174,7 @@ fn foo(v: Vec<i32>) -> Vec<i32> {
}
```
This would get very tedius. It gets worse the more things we want to take ownership of:
This would get very tedious. It gets worse the more things we want to take ownership of:
```rust
fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {

View file

@ -15,7 +15,7 @@ let x = true;
let y: bool = false;
```
A common use of booleans is in [`if` statements][if].
A common use of booleans is in [`if` conditionals][if].
[if]: if.html
@ -176,7 +176,7 @@ Slices have type `&[T]`. Well talk about that `T` when we cover
[generics]: generics.html
You can find more documentation for `slices`s [in the standard library
You can find more documentation for slices [in the standard library
documentation][slice].
[slice]: ../std/primitive.slice.html

View file

@ -6,7 +6,7 @@ become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own
chapter:
* [ownership][ownership], ownership, the key concept
* [ownership][ownership], the key concept
* borrowing, which youre reading now
* [lifetimes][lifetimes], an advanced concept of borrowing
@ -312,6 +312,7 @@ println!("{}", y);
We get this error:
```text
error: `x` does not live long enough
y = &x;
^
@ -334,3 +335,37 @@ In other words, `y` is only valid for the scope where `x` exists. As soon as
`x` goes away, it becomes invalid to refer to it. As such, the error says that
the borrow doesnt live long enough because its not valid for the right
amount of time.
The same problem occurs when the reference is declared _before_ the variable it refers to:
```rust,ignore
let y: &i32;
let x = 5;
y = &x;
println!("{}", y);
```
We get this error:
```text
error: `x` does not live long enough
y = &x;
^
note: reference must be valid for the block suffix following statement 0 at
2:16...
let y: &i32;
let x = 5;
y = &x;
println!("{}", y);
}
note: ...but borrowed value is only valid for the block suffix following
statement 1 at 3:14
let x = 5;
y = &x;
println!("{}", y);
}
```

View file

@ -1,3 +1,570 @@
% The Stack and the Heap
Coming Soon
As a systems language, Rust operates at a low level. If youre coming from a
high-level language, there are some aspects of systems programming that you may
not be familiar with. The most important one is how memory works, with a stack
and a heap. If youre familiar with how C-like languages use stack allocation,
this chapter will be a refresher. If youre not, youll learn about this more
general concept, but with a Rust-y focus.
# Memory management
These two terms are about memory management. The stack and the heap are
abstractions that help you determine when to allocate and deallocate memory.
Heres a high-level comparison:
The stack is very fast, and is where memory is allocated in Rust by default.
But the allocation is local to a function call, and is limited in size. The
heap, on the other hand, is slower, and is explicitly allocated by your
program. But its effectively unlimited in size, and is globally accessible.
# The Stack
Lets talk about this Rust program:
```rust
fn main() {
let x = 42;
}
```
This program has one variable binding, `x`. This memory needs to be allocated
from somewhere. Rust stack allocates by default, which means that basic
values go on the stack. What does that mean?
Well, when a function gets called, some memory gets allocated for all of its
local variables and some other information. This is called a stack frame, and
for the purpose of this tutorial, were going to ignore the extra information
and just consider the local variables were allocating. So in this case, when
`main()` is run, well allocate a single 32-bit integer for our stack frame.
This is automatically handled for you, as you can see, we didnt have to write
any special Rust code or anything.
When the function is over, its stack frame gets deallocated. This happens
automatically, we didnt have to do anything special here.
Thats all there is for this simple program. The key thing to understand here
is that stack allocation is very, very fast. Since we know all the local
variables we have ahead of time, we can grab the memory all at once. And since
well throw them all away at the same time as well, we can get rid of it very
fast too.
The downside is that we cant keep values around if we need them for longer
than a single function. We also havent talked about what that name, stack
means. To do that, we need a slightly more complicated example:
```rust
fn foo() {
let y = 5;
let z = 100;
}
fn main() {
let x = 42;
foo();
}
```
This program has three variables total: two in `foo()`, one in `main()`. Just
as before, when `main()` is called, a single integer is allocated for its stack
frame. But before we can show what happens when `foo()` is called, we need to
visualize whats going on with memory. Your operating system presents a view of
memory to your program thats pretty simple: a huge list of addresses, from 0
to a large number, representing how much RAM your computer has. For example, if
you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,824`. That
number comes from 2<sup>30</sup>, the number of bytes in a gigabyte.
This memory is kind of like a giant array: addresses start at zero and go
up to the final number. So heres a diagram of our first stack frame:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
Weve got `x` located at address `0`, with the value `42`.
When `foo()` is called, a new stack frame is allocated:
| Address | Name | Value |
+---------+------+-------+
| 2 | z | 100 |
| 1 | y | 5 |
| 0 | x | 42 |
Because `0` was taken by the first frame, `1` and `2` are used for `foo()`s
stack frame. It grows upward, the more functions we call.
Theres some important things we have to take note of here. The numbers 0, 1,
and 2 are all solely for illustrative purposes, and bear no relationship to the
actual numbers the computer will actually use. In particular, the series of
addresses are in reality going to be separated by some number of bytes that
separate each address, and that separation may even exceed the size of the
value being stored.
After `foo()` is over, its frame is deallocated:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
And then, after `main()`, even this last value goes away. Easy!
Its called a stack because it works like a stack of dinner plates: the first
plate you put down is the last plate to pick back up. Stacks are sometimes
called last in, first out queues for this reason, as the last value you put
on the stack is the first one you retrieve from it.
Lets try a three-deep example:
```rust
fn bar() {
let i = 6;
}
fn foo() {
let a = 5;
let b = 100;
let c = 1;
bar();
}
fn main() {
let x = 42;
foo();
}
```
Okay, first, we call `main()`:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
Next up, `main()` calls `foo()`:
| Address | Name | Value |
+---------+------+-------+
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
And then `foo()` calls `bar()`:
| Address | Name | Value |
+---------+------+-------+
| 4 | i | 6 |
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
Whew! Our stack is growing tall.
After `bar()` is over, its frame is deallocated, leaving just `foo()` and
`main()`:
| Address | Name | Value |
+---------+------+-------+
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
And then `foo()` ends, leaving just `main()`
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
And then were done. Getting the hang of it? Its like piling up dishes: you
add to the top, you take away from the top.
# The Heap
Now, this works pretty well, but not everything can work like this. Sometimes,
you need to pass some memory between different functions, or keep it alive for
longer than a single functions execution. For this, we can use the heap.
In Rust, you can allocate memory on the heap with the [`Box<T>` type][box].
Heres an example:
```rust
fn main() {
let x = Box::new(5);
let y = 42;
}
```
[box]: ../std/boxed/index.html
Heres what happens in memory when `main()` is called:
| Address | Name | Value |
+---------+------+--------+
| 1 | y | 42 |
| 0 | x | ?????? |
We allocate space for two variables on the stack. `y` is `42`, as it always has
been, but what about `x`? Well, `x` is a `Box<i32>`, and boxes allocate memory
on the heap. The actual value of the box is a structure which has a pointer to
the heap. When we start executing the function, and `Box::new()` is called,
it allocates some memory for the heap, and puts `5` there. The memory now looks
like this:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 5 |
| ... | ... | ... |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
We have 2<sup>30</sup> in our hypothetical computer with 1GB of RAM. And since
our stack grows from zero, the easiest place to allocate memory is from the
other end. So our first value is at the highest place in memory. And the value
of the struct at `x` has a [raw pointer][rawpointer] to the place weve
allocated on the heap, so the value of `x` is 2<sup>30</sup>, the memory
location weve asked for.
[rawpointer]: raw-pointers.html
We havent really talked too much about what it actually means to allocate and
deallocate memory in these contexts. Getting into very deep detail is out of
the scope of this tutorial, but whats important to point out here is that
the heap isnt just a stack that grows from the opposite end. Well have an
example of this later in the book, but because the heap can be allocated and
freed in any order, it can end up with holes. Heres a diagram of the memory
layout of a program which has been running for a while now:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 5 |
| (2<sup>30</sup>) - 1 | | |
| (2<sup>30</sup>) - 2 | | |
| (2<sup>30</sup>) - 3 | | 42 |
| ... | ... | ... |
| 3 | y | (2<sup>30</sup>) - 3 |
| 2 | y | 42 |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
In this case, weve allocated four things on the heap, but deallocated two of
them. Theres a gap between 2<sup>30</sup> and (2<sup>30</sup>) - 3 which isnt
currently being used. The specific details of how and why this happens depends
on what kind of strategy you use to manage the heap. Different programs can use
different memory allocators, which are libraries that manage this for you.
Rust programs use [jemalloc][jemalloc] for this purpose.
[jemalloc]: http://www.canonware.com/jemalloc/
Anyway, back to our example. Since this memory is on the heap, it can stay
alive longer than the function which allocates the box. In this case, however,
it doesnt.[^moving] When the function is over, we need to free the stack frame
for `main()`. `Box<T>`, though, has a trick up its sleve: [Drop][drop]. The
implementation of `Drop` for `Box` deallocates the memory that was allocated
when it was created. Great! So when `x` goes away, it first frees the memory
allocated on the heap:
| Address | Name | Value |
+---------+------+--------+
| 1 | y | 42 |
| 0 | x | ?????? |
[drop]: drop.html
[moving]: We can make the memory live longer by transferring ownership,
sometimes called moving out of the box. More complex examples will
be covered later.
And then the stack frame goes away, freeing all of our memory.
# Arguments and borrowing
Weve got some basic examples with the stack and the heap going, but what about
function arguments and borrowing? Heres a small Rust program:
```rust
fn foo(i: &i32) {
let z = 42;
}
fn main() {
let x = 5;
let y = &x;
foo(y);
}
```
When we enter `main()`, memory looks like this:
| Address | Name | Value |
+---------+------+-------+
| 1 | y | 0 |
| 0 | x | 5 |
`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the
memory location that `x` lives at, which in this case is `0`.
What about when we call `foo()`, passing `y` as an argument?
| Address | Name | Value |
+---------+------+-------+
| 3 | z | 42 |
| 2 | i | 0 |
| 1 | y | 0 |
| 0 | x | 5 |
Stack frames arent just for local bindings, theyre for arguments too. So in
this case, we need to have both `i`, our argument, and `z`, our local variable
binding. `i` is a copy of the argument, `y`. Since `y`s value is `0`, so is
`i`s.
This is one reason why borrowing a variable doesnt deallocate any memory: the
value of a reference is just a pointer to a memory location. If we got rid of
the underlying memory, things wouldnt work very well.
# A complex example
Okay, lets go through this complex program step-by-step:
```rust
fn foo(x: &i32) {
let y = 10;
let z = &y;
baz(z);
bar(x, z);
}
fn bar(a: &i32, b: &i32) {
let c = 5;
let d = Box::new(5);
let e = &d;
baz(e);
}
fn baz(f: &i32) {
let g = 100;
}
fn main() {
let h = 3;
let i = Box::new(20);
let j = &h;
foo(j);
}
```
First, we call `main()`:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
value pointing there.
Next, at the end of `main()`, `foo()` gets called:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
as `j`, since thats what we passed it in. Its a pointer to the `0` address,
since `j` points at `h`.
Next, `foo()` calls `baz()`, passing `z`:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 7 | g | 100 |
| 6 | f | 4 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Weve allocated memory for `f` and `g`. `baz()` is very short, so when its
over, we get rid of its stack frame:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Next, `foo()` calls `bar()` with `x` and `z`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We end up allocating another value on the heap, and so we have to subtract one
from 2<sup>30</sup>. Its easier to just write that than `1,073,741,823`. In any
case, we set up the variables as usual.
At the end of `bar()`, it calls `baz()`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 12 | g | 100 |
| 11 | f | 4 |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
With this, were at our deepest point! Whew! Congrats for following along this
far.
After `baz()` is over, we get rid of `f` and `g`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
what it points to: (2<sup>30</sup>) - 1.
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
And after that, `foo()` returns:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
it will clean up the last of the heap too.
# What do other languages do?
Most languages with a garbage collector heap-allocate by default. This means
that every value is boxed. There are a number of reasons why this is done, but
theyre out of scope for this tutorial. There are some possible optimizations
that dont make it true 100% of the time, too. Rather than relying on the stack
and `Drop` to clean up memory, the garbage collector deals with the heap
instead.
# Which to use?
So if the stack is faster and easier to manage, why do we need the heap? A big
reason is that Stack-allocation alone means you only have LIFO semantics for
reclaiming storage. Heap-allocation is strictly more general, allowing storage
to be taken from and returned to the pool in arbitrary order, but at a
complexity cost.
Generally, you should prefer stack allocation, and so, Rust stack-allocates by
default. The LIFO model of the stack is simpler, at a fundamental level. This
has two big impacts: runtime efficiency and semantic impact.
## Runtime Efficiency.
Managing the memory for the stack is trivial: The machine just
increments or decrements a single value, the so-called “stack pointer”.
Managing memory for the heap is non-trivial: heap-allocated memory is freed at
arbitrary points, and each block of heap-allocated memory can be of arbitrary
size, the memory manager must generally work much harder to identify memory for
reuse.
If youd like to dive into this topic in greater detail, [this paper][wilson]
is a great introduction.
[wilson]: http://www.cs.northwestern.edu/~pdinda/icsclass/doc/dsa.pdf
## Semantic impact
Stack-allocation impacts the Rust language itself, and thus the developers
mental model. The LIFO semantics is what drives how the Rust language handles
automatic memory management. Even the deallocation of a uniquely-owned
heap-allocated box can be driven by the stack-based LIFO semantics, as
discussed throughout this chapter. The flexibility (i.e. expressiveness) of non
LIFO-semantics means that in general the compiler cannot automatically infer at
compile-time where memory should be freed; it has to rely on dynamic protocols,
potentially from outside the language itself, to drive deallocation (reference
counting, as used by `Rc<T>` and `Arc<T>`, is one example of this).
When taken to the extreme, the increased expressive power of heap allocation
comes at the cost of either significant runtime support (e.g. in the form of a
garbage collector) or significant programmer effort (in the form of explicit
memory management calls that require verification not provided by the Rust
compiler).

View file

@ -1,4 +1,4 @@
% while loops
% while Loops
Rust also has a `while` loop. It looks like this:

View file

@ -1,6 +1,8 @@
# Configs
Here are some links to repos with configs which ease the use of rust:
These are some links to repos with configs which ease the use of rust.
## Officially Maintained Configs
* [rust.vim](https://github.com/rust-lang/rust.vim)
* [emacs rust-mode](https://github.com/rust-lang/rust-mode)
@ -8,3 +10,7 @@ Here are some links to repos with configs which ease the use of rust:
* [kate-config](https://github.com/rust-lang/kate-config)
* [nano-config](https://github.com/rust-lang/nano-config)
* [zsh-config](https://github.com/rust-lang/zsh-config)
## Community-maintained Configs
* [.editorconfig](https://gist.github.com/derhuerst/c9d1b9309e308d9851fa) ([what is this?](http://editorconfig.org/))

View file

@ -13,7 +13,6 @@
import os
import sys
import functools
import resource
STATUS = 0
@ -37,6 +36,7 @@ def only_on(platforms):
@only_on(('linux', 'darwin', 'freebsd', 'openbsd'))
def check_rlimit_core():
import resource
soft, hard = resource.getrlimit(resource.RLIMIT_CORE)
if soft > 0:
error_unless_permitted('ALLOW_NONZERO_RLIMIT_CORE', """\

View file

@ -8,6 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::{isize, usize};
#[inline(always)]
fn check_size_and_alignment(size: usize, align: usize) {
debug_assert!(size != 0);
debug_assert!(size <= isize::MAX as usize, "Tried to allocate too much: {} bytes", size);
debug_assert!(usize::is_power_of_two(align), "Invalid alignment of allocation: {}", align);
}
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
/// Return a pointer to `size` bytes of memory aligned to `align`.
@ -19,6 +28,7 @@
/// size on the platform.
#[inline]
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
check_size_and_alignment(size, align);
imp::allocate(size, align)
}
@ -38,6 +48,7 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
check_size_and_alignment(size, align);
imp::reallocate(ptr, old_size, size, align)
}
@ -56,6 +67,7 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usiz
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
align: usize) -> usize {
check_size_and_alignment(size, align);
imp::reallocate_inplace(ptr, old_size, size, align)
}

View file

@ -1537,7 +1537,7 @@ impl BitSet {
bit_vec.nbits = trunc_len * u32::BITS;
}
/// Iterator over each u32 stored in the `BitSet`.
/// Iterator over each usize stored in the `BitSet`.
///
/// # Examples
///
@ -1558,7 +1558,7 @@ impl BitSet {
SetIter {set: self, next_idx: 0}
}
/// Iterator over each u32 stored in `self` union `other`.
/// Iterator over each usize stored in `self` union `other`.
/// See [union_with](#method.union_with) for an efficient in-place version.
///
/// # Examples
@ -1658,7 +1658,7 @@ impl BitSet {
})
}
/// Iterator over each u32 stored in the symmetric difference of `self` and `other`.
/// Iterator over each usize stored in the symmetric difference of `self` and `other`.
/// See [symmetric_difference_with](#method.symmetric_difference_with) for
/// an efficient in-place version.
///
@ -1796,6 +1796,89 @@ impl BitSet {
self.other_op(other, |w1, w2| w1 ^ w2);
}
/// Moves all elements from `other` into `Self`, leaving `other` empty.
///
/// # Examples
///
/// ```
/// # #![feature(collections, bit_set_append_split_off)]
/// use std::collections::{BitVec, BitSet};
///
/// let mut a = BitSet::new();
/// a.insert(2);
/// a.insert(6);
///
/// let mut b = BitSet::new();
/// b.insert(1);
/// b.insert(3);
/// b.insert(6);
///
/// a.append(&mut b);
///
/// assert_eq!(a.len(), 4);
/// assert_eq!(b.len(), 0);
/// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010])));
/// ```
#[unstable(feature = "bit_set_append_split_off",
reason = "recently added as part of collections reform 2")]
pub fn append(&mut self, other: &mut Self) {
self.union_with(other);
other.clear();
}
/// Splits the `BitSet` into two at the given key including the key.
/// Retains the first part in-place while returning the second part.
///
/// # Examples
///
/// ```
/// # #![feature(collections, bit_set_append_split_off)]
/// use std::collections::{BitSet, BitVec};
/// let mut a = BitSet::new();
/// a.insert(2);
/// a.insert(6);
/// a.insert(1);
/// a.insert(3);
///
/// let b = a.split_off(3);
///
/// assert_eq!(a.len(), 2);
/// assert_eq!(b.len(), 2);
/// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100000])));
/// assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b00010010])));
/// ```
#[unstable(feature = "bit_set_append_split_off",
reason = "recently added as part of collections reform 2")]
pub fn split_off(&mut self, at: usize) -> Self {
let mut other = BitSet::new();
if at == 0 {
swap(self, &mut other);
return other;
} else if at >= self.bit_vec.len() {
return other;
}
// Calculate block and bit at which to split
let w = at / u32::BITS;
let b = at % u32::BITS;
// Pad `other` with `w` zero blocks,
// append `self`'s blocks in the range from `w` to the end to `other`
other.bit_vec.storage.extend(repeat(0u32).take(w)
.chain(self.bit_vec.storage[w..].iter().cloned()));
other.bit_vec.nbits = self.bit_vec.nbits;
if b > 0 {
other.bit_vec.storage[w] &= !0 << b;
}
// Sets `bit_vec.len()` and fixes the last block as well
self.bit_vec.truncate(at);
other
}
/// Returns the number of set bits in this set.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -37,6 +37,11 @@ use self::Cow::*;
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`. A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
///
/// `Borrow` is very similar to, but different than, `AsRef`. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
/// Immutably borrows from an owned value.

View file

@ -1002,7 +1002,7 @@ pub trait SliceConcatExt<T: ?Sized> {
/// The resulting type after concatenation
type Output;
/// Flattens a slice of `T` into a single value `U`.
/// Flattens a slice of `T` into a single value `Self::Output`.
///
/// # Examples
///
@ -1012,7 +1012,8 @@ pub trait SliceConcatExt<T: ?Sized> {
#[stable(feature = "rust1", since = "1.0.0")]
fn concat(&self) -> Self::Output;
/// Flattens a slice of `T` into a single value `U`, placing a given separator between each.
/// Flattens a slice of `T` into a single value `Self::Output`, placing a given separator
/// between each.
///
/// # Examples
///

View file

@ -1052,6 +1052,7 @@ impl<T: fmt::Display + ?Sized> ToString for T {
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for String {
#[inline]
fn as_ref(&self) -> &str {
self
}

View file

@ -367,7 +367,7 @@ impl<V> VecMap<V> {
// Move all elements to other
swap(self, &mut other);
return other
} else if at > self.v.len() {
} else if at >= self.v.len() {
// No elements to copy
return other;
}

View file

@ -387,6 +387,67 @@ fn test_bit_vec_clone() {
assert!(b.contains(&1000));
}
#[test]
fn test_bit_set_append() {
let mut a = BitSet::new();
a.insert(2);
a.insert(6);
let mut b = BitSet::new();
b.insert(1);
b.insert(3);
b.insert(6);
a.append(&mut b);
assert_eq!(a.len(), 4);
assert_eq!(b.len(), 0);
assert!(b.capacity() >= 6);
assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010])));
}
#[test]
fn test_bit_set_split_off() {
// Split at 0
let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
0b00110011, 0b01101011, 0b10101101]));
let b = a.split_off(0);
assert_eq!(a.len(), 0);
assert_eq!(b.len(), 21);
assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
0b00110011, 0b01101011, 0b10101101])));
// Split behind last element
let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
0b00110011, 0b01101011, 0b10101101]));
let b = a.split_off(50);
assert_eq!(a.len(), 21);
assert_eq!(b.len(), 0);
assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
0b00110011, 0b01101011, 0b10101101])));
// Split at arbitrary element
let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
0b00110011, 0b01101011, 0b10101101]));
let b = a.split_off(34);
assert_eq!(a.len(), 12);
assert_eq!(b.len(), 9);
assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
0b00110011, 0b01000000])));
assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0, 0, 0, 0,
0b00101011, 0b10101101])));
}
mod bench {
use std::collections::{BitSet, BitVec};
use std::__rand::{Rng, thread_rng, ThreadRng};

View file

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(bit_set_append_split_off)]
#![feature(bit_vec_append_split_off)]
#![feature(box_syntax)]
#![feature(collections)]

View file

@ -24,6 +24,11 @@ use marker::Sized;
/// A cheap, reference-to-reference conversion.
///
/// `AsRef` is very similar to, but different than, `Borrow`. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
///
/// # Examples
///
/// Both `String` and `&str` implement `AsRef<str>`:
@ -173,6 +178,7 @@ impl<T> AsMut<[T]> for [T] {
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for str {
#[inline]
fn as_ref(&self) -> &str {
self
}

View file

@ -137,7 +137,7 @@ pub trait Iterator {
///
/// ```
/// let a = [1, 2, 3, 4, 5];
/// assert_eq!(a.iter().last().unwrap(), &5);
/// assert_eq!(a.iter().last(), Some(&5));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -155,7 +155,7 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert_eq!(it.nth(2).unwrap(), &3);
/// assert_eq!(it.nth(2), Some(&3));
/// assert_eq!(it.nth(2), None);
/// ```
#[inline]
@ -178,8 +178,8 @@ pub trait Iterator {
/// let a = [0];
/// let b = [1];
/// let mut it = a.iter().chain(b.iter());
/// assert_eq!(it.next().unwrap(), &0);
/// assert_eq!(it.next().unwrap(), &1);
/// assert_eq!(it.next(), Some(&0));
/// assert_eq!(it.next(), Some(&1));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -201,7 +201,7 @@ pub trait Iterator {
/// let a = [0];
/// let b = [1];
/// let mut it = a.iter().zip(b.iter());
/// assert_eq!(it.next().unwrap(), (&0, &1));
/// assert_eq!(it.next(), Some((&0, &1)));
/// assert!(it.next().is_none());
/// ```
///
@ -234,8 +234,8 @@ pub trait Iterator {
/// ```
/// let a = [1, 2];
/// let mut it = a.iter().map(|&x| 2 * x);
/// assert_eq!(it.next().unwrap(), 2);
/// assert_eq!(it.next().unwrap(), 4);
/// assert_eq!(it.next(), Some(2));
/// assert_eq!(it.next(), Some(4));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -255,7 +255,7 @@ pub trait Iterator {
/// ```
/// let a = [1, 2];
/// let mut it = a.iter().filter(|&x| *x > 1);
/// assert_eq!(it.next().unwrap(), &2);
/// assert_eq!(it.next(), Some(&2));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -275,7 +275,7 @@ pub trait Iterator {
/// ```
/// let a = [1, 2];
/// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None});
/// assert_eq!(it.next().unwrap(), 4);
/// assert_eq!(it.next(), Some(4));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -310,8 +310,8 @@ pub trait Iterator {
/// ```
/// let a = [100, 200];
/// let mut it = a.iter().enumerate();
/// assert_eq!(it.next().unwrap(), (0, &100));
/// assert_eq!(it.next().unwrap(), (1, &200));
/// assert_eq!(it.next(), Some((0, &100)));
/// assert_eq!(it.next(), Some((1, &200)));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -353,9 +353,9 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().skip_while(|&a| *a < 3);
/// assert_eq!(it.next().unwrap(), &3);
/// assert_eq!(it.next().unwrap(), &4);
/// assert_eq!(it.next().unwrap(), &5);
/// assert_eq!(it.next(), Some(&3));
/// assert_eq!(it.next(), Some(&4));
/// assert_eq!(it.next(), Some(&5));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -375,8 +375,8 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().take_while(|&a| *a < 3);
/// assert_eq!(it.next().unwrap(), &1);
/// assert_eq!(it.next().unwrap(), &2);
/// assert_eq!(it.next(), Some(&1));
/// assert_eq!(it.next(), Some(&2));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -395,8 +395,8 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().skip(3);
/// assert_eq!(it.next().unwrap(), &4);
/// assert_eq!(it.next().unwrap(), &5);
/// assert_eq!(it.next(), Some(&4));
/// assert_eq!(it.next(), Some(&5));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -413,9 +413,9 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().take(3);
/// assert_eq!(it.next().unwrap(), &1);
/// assert_eq!(it.next().unwrap(), &2);
/// assert_eq!(it.next().unwrap(), &3);
/// assert_eq!(it.next(), Some(&1));
/// assert_eq!(it.next(), Some(&2));
/// assert_eq!(it.next(), Some(&3));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -437,11 +437,11 @@ pub trait Iterator {
/// *fac = *fac * x;
/// Some(*fac)
/// });
/// assert_eq!(it.next().unwrap(), 1);
/// assert_eq!(it.next().unwrap(), 2);
/// assert_eq!(it.next().unwrap(), 6);
/// assert_eq!(it.next().unwrap(), 24);
/// assert_eq!(it.next().unwrap(), 120);
/// assert_eq!(it.next(), Some(1));
/// assert_eq!(it.next(), Some(2));
/// assert_eq!(it.next(), Some(6));
/// assert_eq!(it.next(), Some(24));
/// assert_eq!(it.next(), Some(120));
/// assert!(it.next().is_none());
/// ```
#[inline]
@ -680,7 +680,7 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3);
/// assert_eq!(it.find(|&x| *x == 3), Some(&3));
/// assert_eq!(it.collect::<Vec<_>>(), [&4, &5]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -715,7 +715,7 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert_eq!(it.position(|x| *x == 3).unwrap(), 2);
/// assert_eq!(it.position(|x| *x == 3), Some(2));
/// assert_eq!(it.collect::<Vec<_>>(), [&4, &5]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -743,7 +743,7 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 2, 4, 5];
/// let mut it = a.iter();
/// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2);
/// assert_eq!(it.rposition(|x| *x == 2), Some(2));
/// assert_eq!(it.collect::<Vec<_>>(), [&1, &2]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -773,7 +773,7 @@ pub trait Iterator {
///
/// ```
/// let a = [1, 2, 3, 4, 5];
/// assert_eq!(a.iter().max().unwrap(), &5);
/// assert_eq!(a.iter().max(), Some(&5));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -796,7 +796,7 @@ pub trait Iterator {
///
/// ```
/// let a = [1, 2, 3, 4, 5];
/// assert_eq!(a.iter().min().unwrap(), &1);
/// assert_eq!(a.iter().min(), Some(&1));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -1025,9 +1025,9 @@ pub trait Iterator {
/// ```
/// let a = [1, 2];
/// let mut it = a.iter().cycle();
/// assert_eq!(it.next().unwrap(), &1);
/// assert_eq!(it.next().unwrap(), &2);
/// assert_eq!(it.next().unwrap(), &1);
/// assert_eq!(it.next(), Some(&1));
/// assert_eq!(it.next(), Some(&2));
/// assert_eq!(it.next(), Some(&1));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]

View file

@ -140,7 +140,7 @@ impl<T> SliceExt for [T] {
assume(!p.is_null());
if mem::size_of::<T>() == 0 {
Iter {ptr: p,
end: (p as usize + self.len()) as *const T,
end: ((p as usize).wrapping_add(self.len())) as *const T,
_marker: marker::PhantomData}
} else {
Iter {ptr: p,
@ -277,7 +277,7 @@ impl<T> SliceExt for [T] {
assume(!p.is_null());
if mem::size_of::<T>() == 0 {
IterMut {ptr: p,
end: (p as usize + self.len()) as *mut T,
end: ((p as usize).wrapping_add(self.len())) as *mut T,
_marker: marker::PhantomData}
} else {
IterMut {ptr: p,
@ -632,35 +632,17 @@ fn size_from_ptr<T>(_: *const T) -> usize {
// Use macros to be generic over const/mut
//
// They require non-negative `$by` because otherwise the expression
// `(ptr as usize + $by)` would interpret `-1` as `usize::MAX` (and
// thus trigger a panic when overflow checks are on).
// Use this to do `$ptr + $by`, where `$by` is non-negative.
macro_rules! slice_add_offset {
macro_rules! slice_offset {
($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
transmute(ptr as usize + $by)
transmute((ptr as isize).wrapping_add($by))
} else {
ptr.offset($by)
}
}};
}
// Use this to do `$ptr - $by`, where `$by` is non-negative.
macro_rules! slice_sub_offset {
($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
transmute(ptr as usize - $by)
} else {
ptr.offset(-$by)
}
}};
}
macro_rules! slice_ref {
($ptr:expr) => {{
let ptr = $ptr;
@ -683,14 +665,16 @@ macro_rules! iterator {
#[inline]
fn next(&mut self) -> Option<$elem> {
// could be implemented with slices, but this avoids bounds checks
unsafe {
::intrinsics::assume(!self.ptr.is_null());
::intrinsics::assume(!self.end.is_null());
if self.ptr == self.end {
None
} else {
if self.ptr == self.end {
None
} else {
unsafe {
if mem::size_of::<T>() != 0 {
::intrinsics::assume(!self.ptr.is_null());
::intrinsics::assume(!self.end.is_null());
}
let old = self.ptr;
self.ptr = slice_add_offset!(self.ptr, 1);
self.ptr = slice_offset!(self.ptr, 1);
Some(slice_ref!(old))
}
}
@ -698,7 +682,7 @@ macro_rules! iterator {
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let diff = (self.end as usize) - (self.ptr as usize);
let diff = (self.end as usize).wrapping_sub(self.ptr as usize);
let size = mem::size_of::<T>();
let exact = diff / (if size == 0 {1} else {size});
(exact, Some(exact))
@ -726,13 +710,15 @@ macro_rules! iterator {
#[inline]
fn next_back(&mut self) -> Option<$elem> {
// could be implemented with slices, but this avoids bounds checks
unsafe {
::intrinsics::assume(!self.ptr.is_null());
::intrinsics::assume(!self.end.is_null());
if self.end == self.ptr {
None
} else {
self.end = slice_sub_offset!(self.end, 1);
if self.end == self.ptr {
None
} else {
unsafe {
self.end = slice_offset!(self.end, -1);
if mem::size_of::<T>() != 0 {
::intrinsics::assume(!self.ptr.is_null());
::intrinsics::assume(!self.end.is_null());
}
Some(slice_ref!(self.end))
}
}
@ -742,29 +728,29 @@ macro_rules! iterator {
}
macro_rules! make_slice {
($t: ty => $result: ty: $start: expr, $end: expr) => {{
let diff = $end as usize - $start as usize;
let len = if mem::size_of::<T>() == 0 {
diff
($start: expr, $end: expr) => {{
let start = $start;
let diff = ($end as usize).wrapping_sub(start as usize);
if size_from_ptr(start) == 0 {
// use a non-null pointer value
unsafe { from_raw_parts(1 as *const _, diff) }
} else {
diff / mem::size_of::<$t>()
};
unsafe {
from_raw_parts($start, len)
let len = diff / size_from_ptr(start);
unsafe { from_raw_parts(start, len) }
}
}}
}
macro_rules! make_mut_slice {
($t: ty => $result: ty: $start: expr, $end: expr) => {{
let diff = $end as usize - $start as usize;
let len = if mem::size_of::<T>() == 0 {
diff
($start: expr, $end: expr) => {{
let start = $start;
let diff = ($end as usize).wrapping_sub(start as usize);
if size_from_ptr(start) == 0 {
// use a non-null pointer value
unsafe { from_raw_parts_mut(1 as *mut _, diff) }
} else {
diff / mem::size_of::<$t>()
};
unsafe {
from_raw_parts_mut($start, len)
let len = diff / size_from_ptr(start);
unsafe { from_raw_parts_mut(start, len) }
}
}}
}
@ -787,14 +773,14 @@ impl<'a, T> Iter<'a, T> {
/// iterator can continue to be used while this exists.
#[unstable(feature = "core")]
pub fn as_slice(&self) -> &'a [T] {
make_slice!(T => &'a [T]: self.ptr, self.end)
make_slice!(self.ptr, self.end)
}
// Helper function for Iter::nth
fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
match self.as_slice().get(n) {
Some(elem_ref) => unsafe {
self.ptr = slice_add_offset!(elem_ref as *const _, 1);
self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
Some(slice_ref!(elem_ref))
},
None => {
@ -827,12 +813,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> {
fn idx(&mut self, index: usize) -> Option<&'a T> {
unsafe {
if index < self.indexable() {
if mem::size_of::<T>() == 0 {
// Use a non-null pointer value
Some(&mut *(1 as *mut _))
} else {
Some(transmute(self.ptr.offset(index as isize)))
}
Some(slice_ref!(self.ptr.offset(index as isize)))
} else {
None
}
@ -860,14 +841,14 @@ impl<'a, T> IterMut<'a, T> {
/// restricted lifetimes that do not consume the iterator.
#[unstable(feature = "core")]
pub fn into_slice(self) -> &'a mut [T] {
make_mut_slice!(T => &'a mut [T]: self.ptr, self.end)
make_mut_slice!(self.ptr, self.end)
}
// Helper function for IterMut::nth
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
match make_mut_slice!(self.ptr, self.end).get_mut(n) {
Some(elem_ref) => unsafe {
self.ptr = slice_add_offset!(elem_ref as *mut _, 1);
self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
Some(slice_ref!(elem_ref))
},
None => {

View file

@ -44,8 +44,11 @@ pub trait FromStr {
#[stable(feature = "rust1", since = "1.0.0")]
type Err;
/// Parses a string `s` to return an optional value of this type. If the
/// string is ill-formatted, the None is returned.
/// Parses a string `s` to return a value of this type.
///
/// If parsing succeeds, return the value inside `Ok`, otherwise
/// when the string is ill-formatted return an error specific to the
/// inside `Err`. The error type is specific to implementation of the trait.
#[stable(feature = "rust1", since = "1.0.0")]
fn from_str(s: &str) -> Result<Self, Self::Err>;
}

View file

@ -5722,6 +5722,9 @@ pub mod funcs {
pub fn tcgetpgrp(fd: c_int) -> pid_t;
pub fn ttyname(fd: c_int) -> *mut c_char;
pub fn unlink(c: *const c_char) -> c_int;
pub fn wait(status: *const c_int) -> pid_t;
pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int)
-> pid_t;
pub fn write(fd: c_int, buf: *const c_void, count: size_t)
-> ssize_t;
pub fn pread(fd: c_int, buf: *mut c_void, count: size_t,
@ -5773,6 +5776,9 @@ pub mod funcs {
pub fn sysconf(name: c_int) -> c_long;
pub fn ttyname(fd: c_int) -> *mut c_char;
pub fn unlink(c: *const c_char) -> c_int;
pub fn wait(status: *const c_int) -> pid_t;
pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int)
-> pid_t;
pub fn write(fd: c_int, buf: *const c_void, count: size_t)
-> ssize_t;
pub fn pread(fd: c_int, buf: *mut c_void, count: size_t,

View file

@ -273,8 +273,8 @@ See also http://doc.rust-lang.org/book/unsafe.html
E0137: r##"
This error indicates that the compiler found multiple functions with the
#[main] attribute. This is an error because there must be a unique entry point
into a Rust program.
`#[main]` attribute. This is an error because there must be a unique entry
point into a Rust program.
"##,
E0152: r##"
@ -745,6 +745,7 @@ variable.
For example:
```
let x: i32 = "I am not a number!";
// ~~~ ~~~~~~~~~~~~~~~~~~~~
// | |
@ -752,6 +753,7 @@ let x: i32 = "I am not a number!";
// | compiler infers type `&str`
// |
// type `i32` assigned to variable `x`
```
"##,
E0309: r##"
@ -760,6 +762,7 @@ how long the data stored within them is guaranteed to be live. This lifetime
must be as long as the data needs to be alive, and missing the constraint that
denotes this will cause this error.
```
// This won't compile because T is not constrained, meaning the data
// stored in it is not guaranteed to last as long as the reference
struct Foo<'a, T> {
@ -770,6 +773,7 @@ struct Foo<'a, T> {
struct Foo<'a, T: 'a> {
foo: &'a T
}
```
"##,
E0310: r##"
@ -778,6 +782,7 @@ how long the data stored within them is guaranteed to be live. This lifetime
must be as long as the data needs to be alive, and missing the constraint that
denotes this will cause this error.
```
// This won't compile because T is not constrained to the static lifetime
// the reference needs
struct Foo<T> {
@ -788,6 +793,7 @@ struct Foo<T> {
struct Foo<T: 'static> {
foo: &'static T
}
```
"##
}

View file

@ -189,6 +189,7 @@ pub const tag_item_impl_vtables: usize = 0x7e;
pub const tag_impls: usize = 0x109; // top-level only
pub const tag_impls_impl: usize = 0x7f;
pub const tag_impls_impl_trait_def_id: usize = 0x8d;
pub const tag_items_data_item_inherent_impl: usize = 0x80;
pub const tag_items_data_item_extension_impl: usize = 0x81;

View file

@ -304,31 +304,23 @@ pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
decoder::get_native_libraries(&*cdata)
}
pub fn each_impl<F>(cstore: &cstore::CStore,
crate_num: ast::CrateNum,
callback: F) where
F: FnMut(ast::DefId),
{
let cdata = cstore.get_crate_data(crate_num);
decoder::each_impl(&*cdata, callback)
}
pub fn each_implementation_for_type<F>(cstore: &cstore::CStore,
def_id: ast::DefId,
callback: F) where
pub fn each_inherent_implementation_for_type<F>(cstore: &cstore::CStore,
def_id: ast::DefId,
callback: F) where
F: FnMut(ast::DefId),
{
let cdata = cstore.get_crate_data(def_id.krate);
decoder::each_implementation_for_type(&*cdata, def_id.node, callback)
decoder::each_inherent_implementation_for_type(&*cdata, def_id.node, callback)
}
pub fn each_implementation_for_trait<F>(cstore: &cstore::CStore,
def_id: ast::DefId,
callback: F) where
mut callback: F) where
F: FnMut(ast::DefId),
{
let cdata = cstore.get_crate_data(def_id.krate);
decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
cstore.iter_crate_data(|_, cdata| {
decoder::each_implementation_for_trait(cdata, def_id, &mut callback)
})
}
/// If the given def ID describes an item belonging to a trait (either a

View file

@ -21,7 +21,8 @@ use metadata::common::*;
use metadata::csearch::MethodInfo;
use metadata::csearch;
use metadata::cstore;
use metadata::tydecode::{parse_ty_data, parse_region_data, parse_def_id,
use metadata::encoder::def_to_u64;
use metadata::tydecode::{parse_ty_data, parse_region_data,
parse_type_param_def_data, parse_bare_fn_ty_data,
parse_trait_ref_data, parse_predicate_data};
use middle::def;
@ -190,29 +191,32 @@ fn item_symbol(item: rbml::Doc) -> String {
reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string()
}
fn item_parent_item(d: rbml::Doc) -> Option<ast::DefId> {
fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> ast::DefId {
let id = reader::doc_as_u64(d);
let def_id = ast::DefId { krate: (id >> 32) as u32, node: id as u32 };
translate_def_id(cdata, def_id)
}
fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option<ast::DefId> {
let mut ret = None;
reader::tagged_docs(d, tag_items_data_parent_item, |did| {
ret = Some(reader::with_doc_data(did, parse_def_id));
ret = Some(translated_def_id(cdata, did));
false
});
ret
}
fn item_reqd_and_translated_parent_item(cnum: ast::CrateNum,
d: rbml::Doc) -> ast::DefId {
let trait_did = item_parent_item(d).expect("item without parent");
ast::DefId { krate: cnum, node: trait_did.node }
fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> ast::DefId {
translated_def_id(cdata, reader::get_doc(d, tag_items_data_parent_item))
}
fn item_def_id(d: rbml::Doc, cdata: Cmd) -> ast::DefId {
let tagdoc = reader::get_doc(d, tag_def_id);
return translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
translated_def_id(cdata, reader::get_doc(d, tag_def_id))
}
fn get_provided_source(d: rbml::Doc, cdata: Cmd) -> Option<ast::DefId> {
reader::maybe_get_doc(d, tag_item_method_provided_source).map(|doc| {
translate_def_id(cdata, reader::with_doc_data(doc, parse_def_id))
translated_def_id(cdata, doc)
})
}
@ -261,14 +265,12 @@ fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
}
fn enum_variant_ids(item: rbml::Doc, cdata: Cmd) -> Vec<ast::DefId> {
let mut ids: Vec<ast::DefId> = Vec::new();
let v = tag_items_data_item_variant;
reader::tagged_docs(item, v, |p| {
let ext = reader::with_doc_data(p, parse_def_id);
ids.push(ast::DefId { krate: cdata.cnum, node: ext.node });
let mut ids = vec![];
reader::tagged_docs(item, tag_items_data_item_variant, |p| {
ids.push(translated_def_id(cdata, p));
true
});
return ids;
ids
}
fn item_path(item_doc: rbml::Doc) -> Vec<ast_map::PathElem> {
@ -303,8 +305,7 @@ fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
}
}
fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
-> DefLike {
fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: ast::DefId) -> DefLike {
let fam = item_family(item);
match fam {
Constant => {
@ -314,11 +315,9 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
// See the comment for methods below.
let provenance = if reader::maybe_get_doc(
item, tag_item_trait_parent_sort).is_some() {
def::FromTrait(item_reqd_and_translated_parent_item(cnum,
item))
def::FromTrait(item_require_parent_item(cdata, item))
} else {
def::FromImpl(item_reqd_and_translated_parent_item(cnum,
item))
def::FromImpl(item_require_parent_item(cdata, item))
};
DlDef(def::DefAssociatedConst(did, provenance))
} else {
@ -339,17 +338,15 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
// a trait_parent_sort.
let provenance = if reader::maybe_get_doc(
item, tag_item_trait_parent_sort).is_some() {
def::FromTrait(item_reqd_and_translated_parent_item(cnum,
item))
def::FromTrait(item_require_parent_item(cdata, item))
} else {
def::FromImpl(item_reqd_and_translated_parent_item(cnum,
item))
def::FromImpl(item_require_parent_item(cdata, item))
};
DlDef(def::DefMethod(did, provenance))
}
Type => {
if item_sort(item) == Some('t') {
let trait_did = item_reqd_and_translated_parent_item(cnum, item);
let trait_did = item_require_parent_item(cdata, item);
DlDef(def::DefAssociatedTy(trait_did, did))
} else {
DlDef(def::DefTy(did, false))
@ -358,11 +355,11 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
Mod => DlDef(def::DefMod(did)),
ForeignMod => DlDef(def::DefForeignMod(did)),
StructVariant => {
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
let enum_did = item_require_parent_item(cdata, item);
DlDef(def::DefVariant(enum_did, did, true))
}
TupleVariant => {
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
let enum_did = item_require_parent_item(cdata, item);
DlDef(def::DefVariant(enum_did, did, false))
}
Trait => DlDef(def::DefTrait(did)),
@ -560,9 +557,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
{
// Iterate over all children.
let _ = reader::tagged_docs(item_doc, tag_mod_child, |child_info_doc| {
let child_def_id = reader::with_doc_data(child_info_doc,
parse_def_id);
let child_def_id = translate_def_id(cdata, child_def_id);
let child_def_id = translated_def_id(cdata, child_info_doc);
// This item may be in yet another crate if it was the child of a
// reexport.
@ -584,9 +579,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
Some(child_item_doc) => {
// Hand off the item to the callback.
let child_name = item_name(&*intr, child_item_doc);
let def_like = item_to_def_like(child_item_doc,
child_def_id,
cdata.cnum);
let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
let visibility = item_visibility(child_item_doc);
callback(def_like, child_name, visibility);
@ -615,9 +608,8 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
if let StaticMethod = item_family(impl_method_doc) {
// Hand off the static method to the callback.
let static_method_name = item_name(&*intr, impl_method_doc);
let static_method_def_like = item_to_def_like(impl_method_doc,
impl_item_def_id,
cdata.cnum);
let static_method_def_like = item_to_def_like(cdata, impl_method_doc,
impl_item_def_id);
callback(static_method_def_like,
static_method_name,
item_visibility(impl_method_doc));
@ -633,9 +625,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
let _ = each_reexport(item_doc, |reexport_doc| {
let def_id_doc = reader::get_doc(reexport_doc,
tag_items_data_item_reexport_def_id);
let child_def_id = reader::with_doc_data(def_id_doc,
parse_def_id);
let child_def_id = translate_def_id(cdata, child_def_id);
let child_def_id = translated_def_id(cdata, def_id_doc);
let name_doc = reader::get_doc(reexport_doc,
tag_items_data_item_reexport_name);
@ -657,9 +647,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
// Get the item.
if let Some(child_item_doc) = maybe_find_item(child_def_id.node, other_crates_items) {
// Hand off the item to the callback.
let def_like = item_to_def_like(child_item_doc,
child_def_id,
child_def_id.krate);
let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
// These items have a public visibility because they're part of
// a public re-export.
callback(def_like, token::intern(name), ast::Public);
@ -733,9 +721,8 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
match decode_inlined_item(cdata, tcx, path, item_doc) {
Ok(ii) => csearch::FoundAst::Found(ii),
Err(path) => {
match item_parent_item(item_doc) {
match item_parent_item(cdata, item_doc) {
Some(did) => {
let did = translate_def_id(cdata, did);
let parent_item = lookup_item(did.node, cdata.data());
match decode_inlined_item(cdata, tcx, path, parent_item) {
Ok(ii) => csearch::FoundAst::FoundParent(did, ii),
@ -759,7 +746,7 @@ pub fn get_enum_variant_defs(intr: &IdentInterner,
let item = find_item(did.node, items);
let name = item_name(intr, item);
let visibility = item_visibility(item);
match item_to_def_like(item, *did, cdata.cnum) {
match item_to_def_like(cdata, item, *did) {
DlDef(def @ def::DefVariant(..)) => (def, name, visibility),
_ => unreachable!()
}
@ -889,8 +876,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
let def_id = item_def_id(method_doc, cdata);
let container_id = item_reqd_and_translated_parent_item(cdata.cnum,
method_doc);
let container_id = item_require_parent_item(cdata, method_doc);
let container_doc = lookup_item(container_id.node, cdata.data());
let container = match item_family(container_doc) {
Trait => TraitContainer(container_id),
@ -1094,7 +1080,7 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
let item = lookup_item(node_id, cdata.data());
let mut ret = None;
reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor, |_| {
ret = Some(item_reqd_and_translated_parent_item(cdata.cnum, item));
ret = Some(item_require_parent_item(cdata, item));
false
});
ret
@ -1144,7 +1130,7 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
let name = item_name(&*intr, an_item);
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
let origin_id = translated_def_id(cdata, tagdoc);
result.push(ty::field_ty {
name: name,
id: did,
@ -1158,7 +1144,7 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let f = item_family(an_item);
let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
let origin_id = translated_def_id(cdata, tagdoc);
result.push(ty::field_ty {
name: special_idents::unnamed_field.name,
id: did,
@ -1342,55 +1328,77 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId {
}
}
pub fn each_impl<F>(cdata: Cmd, mut callback: F) where
F: FnMut(ast::DefId),
{
let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| {
callback(item_def_id(impl_doc, cdata));
true
});
// Translate a DefId from the current compilation environment to a DefId
// for an external crate.
fn reverse_translate_def_id(cdata: Cmd, did: ast::DefId) -> Option<ast::DefId> {
if did.krate == cdata.cnum {
return Some(ast::DefId { krate: ast::LOCAL_CRATE, node: did.node });
}
for (&local, &global) in &cdata.cnum_map {
if global == did.krate {
return Some(ast::DefId { krate: local, node: did.node });
}
}
None
}
pub fn each_implementation_for_type<F>(cdata: Cmd,
id: ast::NodeId,
mut callback: F)
pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
id: ast::NodeId,
mut callback: F)
where F: FnMut(ast::DefId),
{
let item_doc = lookup_item(id, cdata.data());
reader::tagged_docs(item_doc,
tag_items_data_item_inherent_impl,
|impl_doc| {
let implementation_def_id = item_def_id(impl_doc, cdata);
callback(implementation_def_id);
if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() {
callback(item_def_id(impl_doc, cdata));
}
true
});
}
pub fn each_implementation_for_trait<F>(cdata: Cmd,
id: ast::NodeId,
def_id: ast::DefId,
mut callback: F) where
F: FnMut(ast::DefId),
{
let item_doc = lookup_item(id, cdata.data());
if cdata.cnum == def_id.krate {
let item_doc = lookup_item(def_id.node, cdata.data());
let _ = reader::tagged_docs(item_doc,
tag_items_data_item_extension_impl,
|impl_doc| {
callback(item_def_id(impl_doc, cdata));
true
});
return;
}
let _ = reader::tagged_docs(item_doc,
tag_items_data_item_extension_impl,
|impl_doc| {
let implementation_def_id = item_def_id(impl_doc, cdata);
callback(implementation_def_id);
true
});
// Do a reverse lookup beforehand to avoid touching the crate_num
// hash map in the loop below.
if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) {
let def_id_u64 = def_to_u64(crate_local_did);
let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| {
let impl_trait = reader::get_doc(impl_doc, tag_impls_impl_trait_def_id);
if reader::doc_as_u64(impl_trait) == def_id_u64 {
callback(item_def_id(impl_doc, cdata));
}
true
});
}
}
pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
-> Option<ast::DefId> {
let item_doc = lookup_item(id, cdata.data());
let parent_item_id = match item_parent_item(item_doc) {
let parent_item_id = match item_parent_item(cdata, item_doc) {
None => return None,
Some(item_id) => item_id,
};
let parent_item_id = translate_def_id(cdata, parent_item_id);
let parent_item_doc = lookup_item(parent_item_id.node, cdata.data());
match item_family(parent_item_doc) {
Trait => Some(item_def_id(parent_item_doc, cdata)),
@ -1538,8 +1546,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
let name = item_name(&*token::get_ident_interner(), ident_str_doc);
let def_id_doc = reader::get_doc(rp_doc,
tag_region_param_def_def_id);
let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
let def_id = translate_def_id(cdata, def_id);
let def_id = translated_def_id(cdata, def_id_doc);
let doc = reader::get_doc(rp_doc, tag_region_param_def_space);
let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as usize);

View file

@ -91,8 +91,8 @@ fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Name) {
rbml_w.wr_tagged_str(tag_item_impl_type_basename, &token::get_name(name));
}
pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
rbml_w.wr_tagged_str(tag_def_id, &def_to_string(id));
fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
}
#[derive(Clone)]
@ -122,6 +122,10 @@ fn encode_family(rbml_w: &mut Encoder, c: char) {
rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8);
}
pub fn def_to_u64(did: DefId) -> u64 {
(did.krate as u64) << 32 | (did.node as u64)
}
pub fn def_to_string(did: DefId) -> String {
format!("{}:{}", did.krate, did.node)
}
@ -153,9 +157,9 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
}
fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
let s = def_to_string(vid);
rbml_w.wr_tagged_str(tag_items_data_item_variant, &s[..]);
rbml_w.wr_tagged_str(tag_mod_child, &s[..]);
let id = def_to_u64(vid);
rbml_w.wr_tagged_u64(tag_items_data_item_variant, id);
rbml_w.wr_tagged_u64(tag_mod_child, id);
}
pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
@ -260,7 +264,7 @@ fn encode_disr_val(_: &EncodeContext,
}
fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
rbml_w.wr_tagged_str(tag_items_data_parent_item, &def_to_string(id));
rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id));
}
fn encode_struct_fields(rbml_w: &mut Encoder,
@ -275,7 +279,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder,
}
encode_struct_field_family(rbml_w, f.vis);
encode_def_id(rbml_w, f.id);
rbml_w.wr_tagged_str(tag_item_field_origin, &def_to_string(origin));
rbml_w.wr_tagged_u64(tag_item_field_origin, def_to_u64(origin));
rbml_w.end_tag();
}
}
@ -358,8 +362,8 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder,
debug!("(encode reexported static method) {}::{}",
exp.name, token::get_name(method_name));
rbml_w.start_tag(tag_items_data_item_reexport);
rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id,
&def_to_string(method_def_id));
rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
def_to_u64(method_def_id));
rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
&format!("{}::{}", exp.name,
token::get_name(method_name)));
@ -495,8 +499,8 @@ fn encode_reexports(ecx: &EncodeContext,
exp.def_id.node,
id);
rbml_w.start_tag(tag_items_data_item_reexport);
rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id,
&def_to_string(exp.def_id));
rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
def_to_u64(exp.def_id));
rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
exp.name.as_str());
rbml_w.end_tag();
@ -526,12 +530,12 @@ fn encode_info_for_mod(ecx: &EncodeContext,
// Encode info about all the module children.
for item in &md.items {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(item.id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(item.id)));
each_auxiliary_node_id(&**item, |auxiliary_node_id| {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(auxiliary_node_id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(auxiliary_node_id)));
true
});
@ -541,8 +545,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
token::get_ident(ident),
did, ecx.tcx.map.node_to_string(did));
rbml_w.wr_tagged_str(tag_mod_impl,
&def_to_string(local_def(did)));
rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(local_def(did)));
}
}
@ -619,8 +622,7 @@ fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
fn encode_provided_source(rbml_w: &mut Encoder,
source_opt: Option<DefId>) {
if let Some(source) = source_opt {
rbml_w.wr_tagged_str(tag_item_method_provided_source,
&def_to_string(source));
rbml_w.wr_tagged_u64(tag_item_method_provided_source, def_to_u64(source));
}
}
@ -725,8 +727,8 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
encode_name(rbml_w, param.name);
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_region_param_def_def_id,
&def_to_string(param.def_id));
rbml_w.wr_tagged_u64(tag_region_param_def_def_id,
def_to_u64(param.def_id));
rbml_w.wr_tagged_u64(tag_region_param_def_space,
param.space.to_uint() as u64);
@ -1089,8 +1091,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
// Encode all the items in this module.
for foreign_item in &fm.items {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(foreign_item.id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(foreign_item.id)));
}
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
@ -1335,8 +1337,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
rbml_w.end_tag();
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(method_def_id.def_id()));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(method_def_id.def_id()));
}
encode_path(rbml_w, path.clone());
@ -1893,6 +1895,7 @@ impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
def_id.krate != ast::LOCAL_CRATE {
self.rbml_w.start_tag(tag_impls_impl);
encode_def_id(self.rbml_w, local_def(item.id));
self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id));
self.rbml_w.end_tag();
}
}
@ -1932,12 +1935,12 @@ fn encode_misc_info(ecx: &EncodeContext,
rbml_w.start_tag(tag_misc_info);
rbml_w.start_tag(tag_misc_info_crate_items);
for item in &krate.module.items {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(item.id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(item.id)));
each_auxiliary_node_id(&**item, |auxiliary_node_id| {
rbml_w.wr_tagged_str(tag_mod_child,
&def_to_string(local_def(auxiliary_node_id)));
rbml_w.wr_tagged_u64(tag_mod_child,
def_to_u64(local_def(auxiliary_node_id)));
true
});
}

View file

@ -1125,7 +1125,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
// that case we can adjust the length of the
// original vec accordingly, but we'd have to
// make trans do the right thing, and it would
// only work for `~` vectors. It seems simpler
// only work for `Box<[T]>`s. It seems simpler
// to just require that people call
// `vec.pop()` or `vec.unshift()`.
let slice_bk = ty::BorrowKind::from_mutbl(slice_mutbl);

View file

@ -323,7 +323,7 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
def_id.krate == ast::LOCAL_CRATE
}
ty::ty_uniq(_) => { // treat ~T like Box<T>
ty::ty_uniq(_) => { // Box<T>
let krate = tcx.lang_items.owned_box().map(|d| d.krate);
krate == Some(ast::LOCAL_CRATE)
}

View file

@ -117,23 +117,71 @@ pub enum MethodMatchedData {
/// obligation is for `int`. In that case, we drop the impl out of the
/// list. But the other cases are considered *candidates*.
///
/// Candidates can either be definitive or ambiguous. An ambiguous
/// candidate is one that might match or might not, depending on how
/// type variables wind up being resolved. This only occurs during inference.
/// For selection to succeed, there must be exactly one matching
/// candidate. If the obligation is fully known, this is guaranteed
/// by coherence. However, if the obligation contains type parameters
/// or variables, there may be multiple such impls.
///
/// For selection to succeed, there must be exactly one non-ambiguous
/// candidate. Usually, it is not possible to have more than one
/// definitive candidate, due to the coherence rules. However, there is
/// one case where it could occur: if there is a blanket impl for a
/// trait (that is, an impl applied to all T), and a type parameter
/// with a where clause. In that case, we can have a candidate from the
/// where clause and a second candidate from the impl. This is not a
/// problem because coherence guarantees us that the impl which would
/// be used to satisfy the where clause is the same one that we see
/// now. To resolve this issue, therefore, we ignore impls if we find a
/// matching where clause. Part of the reason for this is that where
/// clauses can give additional information (like, the types of output
/// parameters) that would have to be inferred from the impl.
/// It is not a real problem if multiple matching impls exist because
/// of type variables - it just means the obligation isn't sufficiently
/// elaborated. In that case we report an ambiguity, and the caller can
/// try again after more type information has been gathered or report a
/// "type annotations required" error.
///
/// However, with type parameters, this can be a real problem - type
/// parameters don't unify with regular types, but they *can* unify
/// with variables from blanket impls, and (unless we know its bounds
/// will always be satisfied) picking the blanket impl will be wrong
/// for at least *some* substitutions. To make this concrete, if we have
///
/// trait AsDebug { type Out : fmt::Debug; fn debug(self) -> Self::Out; }
/// impl<T: fmt::Debug> AsDebug for T {
/// type Out = T;
/// fn debug(self) -> fmt::Debug { self }
/// }
/// fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
///
/// we can't just use the impl to resolve the <T as AsDebug> obligation
/// - a type from another crate (that doesn't implement fmt::Debug) could
/// implement AsDebug.
///
/// Because where-clauses match the type exactly, multiple clauses can
/// only match if there are unresolved variables, and we can mostly just
/// report this ambiguity in that case. This is still a problem - we can't
/// *do anything* with ambiguities that involve only regions. This is issue
/// #21974.
///
/// If a single where-clause matches and there are no inference
/// variables left, then it definitely matches and we can just select
/// it.
///
/// In fact, we even select the where-clause when the obligation contains
/// inference variables. The can lead to inference making "leaps of logic",
/// for example in this situation:
///
/// pub trait Foo<T> { fn foo(&self) -> T; }
/// impl<T> Foo<()> for T { fn foo(&self) { } }
/// impl Foo<bool> for bool { fn foo(&self) -> bool { *self } }
///
/// pub fn foo<T>(t: T) where T: Foo<bool> {
/// println!("{:?}", <T as Foo<_>>::foo(&t));
/// }
/// fn main() { foo(false); }
///
/// Here the obligation <T as Foo<$0>> can be matched by both the blanket
/// impl and the where-clause. We select the where-clause and unify $0=bool,
/// so the program prints "false". However, if the where-clause is omitted,
/// the blanket impl is selected, we unify $0=(), and the program prints
/// "()".
///
/// Exactly the same issues apply to projection and object candidates, except
/// that we can have both a projection candidate and a where-clause candidate
/// for the same obligation. In that case either would do (except that
/// different "leaps of logic" would occur if inference variables are
/// present), and we just pick the projection. This is, for example,
/// required for associated types to work in default impls, as the bounds
/// are visible both as projection bounds and as where-clauses from the
/// parameter environment.
#[derive(PartialEq,Eq,Debug,Clone)]
enum SelectionCandidate<'tcx> {
PhantomFnCandidate,
@ -1350,63 +1398,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Returns true if `candidate_i` should be dropped in favor of
/// `candidate_j`. Generally speaking we will drop duplicate
/// candidates and prefer where-clause candidates.
/// Returns true if `victim` should be dropped in favor of
/// `other`. Generally speaking we will drop duplicate
/// candidates and prefer where-clause candidates.
///
/// See the comment for "SelectionCandidate" for more details.
fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
candidate_i: &SelectionCandidate<'tcx>,
candidate_j: &SelectionCandidate<'tcx>)
victim: &SelectionCandidate<'tcx>,
other: &SelectionCandidate<'tcx>)
-> bool
{
if candidate_i == candidate_j {
if victim == other {
return true;
}
match (candidate_i, candidate_j) {
(&ImplCandidate(..), &ParamCandidate(..)) |
(&ClosureCandidate(..), &ParamCandidate(..)) |
(&FnPointerCandidate(..), &ParamCandidate(..)) |
(&BuiltinObjectCandidate(..), &ParamCandidate(_)) |
(&BuiltinCandidate(..), &ParamCandidate(..)) => {
// We basically prefer always prefer to use a
// where-clause over another option. Where clauses
// impose the burden of finding the exact match onto
// the caller. Using an impl in preference of a where
// clause can also lead us to "overspecialize", as in
// #18453.
true
}
(&ImplCandidate(..), &ObjectCandidate(..)) => {
// This means that we are matching an object of type
// `Trait` against the trait `Trait`. In that case, we
// always prefer to use the object vtable over the
// impl. Like a where clause, the impl may or may not
// be the one that is used by the object (because the
// impl may have additional where-clauses that the
// object's source might not meet) -- if it is, using
// the vtable is fine. If it is not, using the vtable
// is good. A win win!
true
}
(&DefaultImplCandidate(_), _) => {
// Prefer other candidates over default implementations.
self.tcx().sess.bug(
"default implementations shouldn't be recorded \
when there are other valid candidates");
}
(&ProjectionCandidate, &ParamCandidate(_)) => {
// FIXME(#20297) -- this gives where clauses precedent
// over projections. Really these are just two means
// of deducing information (one based on the where
// clauses on the trait definition; one based on those
// on the enclosing scope), and it'd be better to
// integrate them more intelligently. But for now this
// seems ok. If we DON'T give where clauses
// precedence, we run into trouble in default methods,
// where both the projection bounds for `Self::A` and
// the where clauses are in scope.
true
}
_ => {
false
}
match other {
&ObjectCandidate(..) |
&ParamCandidate(_) | &ProjectionCandidate => match victim {
&DefaultImplCandidate(..) => {
self.tcx().sess.bug(
"default implementations shouldn't be recorded \
when there are other valid candidates");
}
&PhantomFnCandidate => {
self.tcx().sess.bug("PhantomFn didn't short-circuit selection");
}
&ImplCandidate(..) |
&ClosureCandidate(..) |
&FnPointerCandidate(..) |
&BuiltinObjectCandidate(..) |
&DefaultImplObjectCandidate(..) |
&BuiltinCandidate(..) => {
// We have a where-clause so don't go around looking
// for impls.
true
}
&ObjectCandidate(..) |
&ProjectionCandidate => {
// Arbitrarily give param candidates priority
// over projection and object candidates.
true
},
&ParamCandidate(..) => false,
&ErrorCandidate => false // propagate errors
},
_ => false
}
}
@ -2441,10 +2477,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// `match_impl()`. For example, if `impl_def_id` is declared
/// as:
///
/// impl<T:Copy> Foo for ~T { ... }
/// impl<T:Copy> Foo for Box<T> { ... }
///
/// and `obligation_self_ty` is `int`, we'd back an `Err(_)`
/// result. But if `obligation_self_ty` were `~int`, we'd get
/// and `obligation_self_ty` is `int`, we'd get back an `Err(_)`
/// result. But if `obligation_self_ty` were `Box<int>`, we'd get
/// back `Ok(T=int)`.
fn match_inherent_impl(&mut self,
impl_def_id: ast::DefId,

View file

@ -2564,9 +2564,11 @@ impl<'tcx> TraitDef<'tcx> {
tcx: &ctxt<'tcx>,
impl_def_id: DefId,
impl_trait_ref: TraitRef<'tcx>) {
debug!("TraitDef::record_impl for {}, from {}",
self.repr(tcx), impl_trait_ref.repr(tcx));
// We don't want to borrow_mut after we already populated all impls,
// so check if an impl is present with an immutable borrow first.
if let Some(sty) = fast_reject::simplify_type(tcx,
impl_trait_ref.self_ty(), false) {
if let Some(is) = self.nonblanket_impls.borrow().get(&sty) {
@ -6336,10 +6338,10 @@ pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt,
tcx.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
}
/// Populates the type context with all the implementations for the given type
/// if necessary.
pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
type_id: ast::DefId) {
/// Populates the type context with all the inherent implementations for
/// the given type if necessary.
pub fn populate_inherent_implementations_for_type_if_necessary(tcx: &ctxt,
type_id: ast::DefId) {
if type_id.krate == LOCAL_CRATE {
return
}
@ -6348,37 +6350,15 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
return
}
debug!("populate_implementations_for_type_if_necessary: searching for {:?}", type_id);
debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}", type_id);
let mut inherent_impls = Vec::new();
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| {
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
// Record the implementation, if needed
if let Some(trait_ref) = csearch::get_impl_trait(tcx, impl_def_id) {
let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
trait_def.record_impl(tcx, impl_def_id, trait_ref);
} else {
inherent_impls.push(impl_def_id);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for impl_item_def_id in &impl_items {
let method_def_id = impl_item_def_id.def_id();
match impl_or_trait_item(tcx, method_def_id) {
MethodTraitItem(method) => {
if let Some(source) = method.provided_source {
tcx.provided_method_sources
.borrow_mut()
.insert(method_def_id, source);
}
}
_ => {}
}
}
csearch::each_inherent_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| {
// Record the implementation.
inherent_impls.push(impl_def_id);
// Store the implementation info.
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
});
@ -6388,18 +6368,18 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
/// Populates the type context with all the implementations for the given
/// trait if necessary.
pub fn populate_implementations_for_trait_if_necessary(
tcx: &ctxt,
trait_id: ast::DefId) {
pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast::DefId) {
if trait_id.krate == LOCAL_CRATE {
return
}
let def = lookup_trait_def(tcx, trait_id);
if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
return
return;
}
debug!("populate_implementations_for_trait_if_necessary: searching for {}", def.repr(tcx));
if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) {
record_trait_has_default_impl(tcx, trait_id);
}

View file

@ -637,7 +637,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice<T> {
}
}
// This is necessary to handle types like Option<~[T]>, for which
// This is necessary to handle types like Option<Vec<T>>, for which
// autoderef cannot convert the &[T] handler
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec<T> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {

View file

@ -732,7 +732,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
/// let p: Point;
/// p.x = 22; // ok, even though `p` is uninitialized
///
/// let p: ~Point;
/// let p: Box<Point>;
/// (*p).x = 22; // not ok, p is uninitialized, can't deref
/// ```
fn check_if_assigned_path_is_moved(&self,

View file

@ -1314,7 +1314,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
// `impl [... for] Private` is never visible.
let self_contains_private;
// impl [... for] Public<...>, but not `impl [... for]
// ~[Public]` or `(Public,)` etc.
// Vec<Public>` or `(Public,)` etc.
let self_is_public_path;
// check the properties of the Self type:

View file

@ -10,8 +10,111 @@
#![allow(non_snake_case)]
// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80 characters.
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {
E0154: r##"
Imports (`use` statements) are not allowed after non-item statements, such as
variable declarations and expression statements.
Here is an example that demonstrates the error:
```
fn f() {
// Variable declaration before import
let x = 0;
use std::io::Read;
...
}
```
The solution is to declare the imports at the top of the block, function, or
file.
Here is the previous example again, with the correct order:
```
fn f() {
use std::io::Read;
let x = 0;
...
}
```
See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:
http://doc.rust-lang.org/reference.html#statements
"##,
E0259: r##"
The name chosen for an external crate conflicts with another external crate that
has been imported into the current module.
Wrong example:
```
extern crate a;
extern crate crate_a as a;
```
The solution is to choose a different name that doesn't conflict with any
external crate imported into the current module.
Correct example:
```
extern crate a;
extern crate crate_a as other_name;
```
"##,
E0260: r##"
The name for an item declaration conflicts with an external crate's name.
For instance,
```
extern crate abc;
struct abc;
```
There are two possible solutions:
Solution #1: Rename the item.
```
extern crate abc;
struct xyz;
```
Solution #2: Import the crate with a different name.
```
extern crate abc as xyz;
struct abc;
```
See the Declaration Statements section of the reference for more information
about what constitutes an Item declaration and what does not:
http://doc.rust-lang.org/reference.html#statements
"##,
E0317: r##"
User-defined types or type parameters cannot shadow the primitive types.
This error indicates you tried to define a type, struct or enum with the same
name as an existing primitive type.
See the Types section of the reference for more information about the primitive
types:
http://doc.rust-lang.org/reference.html#types
"##
}
register_diagnostics! {
E0154,
E0157,
E0153,
E0251, // a named type or value has already been imported in this module
@ -22,9 +125,6 @@ register_diagnostics! {
E0256, // import conflicts with type in this module
E0257, // inherent implementations are only allowed on types defined in the current module
E0258, // import conflicts with existing submodule
E0259, // an extern crate has already been imported into this module
E0260, // name conflicts with an external crate that has been imported into this module
E0317, // user-defined types or type parameters cannot shadow the primitive types
E0364, // item is private
E0365 // item is private
}

View file

@ -2688,18 +2688,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
check_ribs: bool)
-> AssocItemResolveResult
{
let max_assoc_types;
match maybe_qself {
Some(&ast::QSelf { position: 0, .. }) =>
return TypecheckRequired,
_ => {}
Some(qself) => {
if qself.position == 0 {
return TypecheckRequired;
}
max_assoc_types = path.segments.len() - qself.position;
// Make sure the trait is valid.
let _ = self.resolve_trait_reference(id, path, max_assoc_types);
}
None => {
max_assoc_types = path.segments.len();
}
}
let max_assoc_types = if let Some(qself) = maybe_qself {
// Make sure the trait is valid.
let _ = self.resolve_trait_reference(id, path, 1);
path.segments.len() - qself.position
} else {
path.segments.len()
};
let mut resolution = self.with_no_errors(|this| {
this.resolve_path(id, path, 0, namespace, check_ribs)

View file

@ -618,7 +618,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
namespace_name,
name_bindings.def_for_namespace(namespace));
self.check_for_conflicting_import(
&import_resolution.target_for_namespace(namespace),
&import_resolution,
directive.span,
target,
namespace);
@ -755,7 +755,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
// Continue.
}
Some(ref value_target) => {
self.check_for_conflicting_import(&dest_import_resolution.value_target,
self.check_for_conflicting_import(&dest_import_resolution,
import_directive.span,
*ident,
ValueNS);
@ -767,7 +767,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
// Continue.
}
Some(ref type_target) => {
self.check_for_conflicting_import(&dest_import_resolution.type_target,
self.check_for_conflicting_import(&dest_import_resolution,
import_directive.span,
*ident,
TypeNS);
@ -887,24 +887,31 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
/// Checks that imported names and items don't have the same name.
fn check_for_conflicting_import(&mut self,
target: &Option<Target>,
import_resolution: &ImportResolution,
import_span: Span,
name: Name,
namespace: Namespace) {
let target = import_resolution.target_for_namespace(namespace);
debug!("check_for_conflicting_import: {}; target exists: {}",
&token::get_name(name),
target.is_some());
match *target {
match target {
Some(ref target) if target.shadowable != Shadowable::Always => {
let msg = format!("a {} named `{}` has already been imported \
in this module",
match namespace {
TypeNS => "type",
ValueNS => "value",
},
let ns_word = match namespace {
TypeNS => "type",
ValueNS => "value",
};
span_err!(self.resolver.session, import_span, E0252,
"a {} named `{}` has already been imported \
in this module", ns_word,
&token::get_name(name));
span_err!(self.resolver.session, import_span, E0252, "{}", &msg[..]);
let use_id = import_resolution.id(namespace);
let item = self.resolver.ast_map.expect_item(use_id);
// item is syntax::ast::Item;
span_note!(self.resolver.session, item.span,
"previous import of `{}` here",
token::get_name(name));
}
Some(_) | None => {}
}

View file

@ -289,7 +289,7 @@ pub fn mangle<PI: Iterator<Item=PathElem>>(path: PI,
// when using unix's linker. Perhaps one day when we just use a linker from LLVM
// we won't need to do this name mangling. The problem with name mangling is
// that it seriously limits the available characters. For example we can't
// have things like &T or ~[T] in symbol names when one would theoretically
// have things like &T in symbol names when one would theoretically
// want them for things like impls of traits on that type.
//
// To be able to work on all platforms and get *some* reasonable output, we

View file

@ -230,8 +230,8 @@ impl<'a> SpanUtils<'a> {
// Reparse span and return an owned vector of sub spans of the first limit
// identifier tokens in the given nesting level.
// example with Foo<Bar<T,V>, Bar<T,V>>
// Nesting = 0: all idents outside of brackets: ~[Foo]
// Nesting = 1: idents within one level of brackets: ~[Bar, Bar]
// Nesting = 0: all idents outside of brackets: Vec<Foo>
// Nesting = 1: idents within one level of brackets: Vec<Bar, Bar>
pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> Vec<Span> {
let mut result: Vec<Span> = vec!();
@ -352,7 +352,7 @@ impl<'a> SpanUtils<'a> {
return vec!();
}
// Type params are nested within one level of brackets:
// i.e. we want ~[A, B] from Foo<A, B<T,U>>
// i.e. we want Vec<A, B> from Foo<A, B<T,U>>
self.spans_with_brackets(span, 1, number)
}

View file

@ -196,7 +196,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
// The `noalias` attribute on the return value is useful to a
// function ptr caller.
match ret_ty.sty {
// `~` pointer return values never alias because ownership
// `Box` pointer return values never alias because ownership
// is transferred
ty::ty_uniq(it) if common::type_is_sized(ccx.tcx(), it) => {
attrs.ret(llvm::Attribute::NoAlias);
@ -239,7 +239,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
attrs.arg(idx, llvm::Attribute::ZExt);
}
// `~` pointer parameters never alias because ownership is transferred
// `Box` pointer parameters never alias because ownership is transferred
ty::ty_uniq(inner) => {
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));

View file

@ -142,26 +142,24 @@ impl<'tcx> TypeMap<'tcx> {
fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
type_: Ty<'tcx>) -> UniqueTypeId {
// basic type -> {:name of the type:}
// tuple -> {tuple_(:param-uid:)*}
// struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
// enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
// enum variant -> {variant_:variant-name:_:enum-uid:}
// reference (&) -> {& :pointee-uid:}
// mut reference (&mut) -> {&mut :pointee-uid:}
// ptr (*) -> {* :pointee-uid:}
// mut ptr (*mut) -> {*mut :pointee-uid:}
// unique ptr (~) -> {~ :pointee-uid:}
// @-ptr (@) -> {@ :pointee-uid:}
// sized vec ([T; x]) -> {[:size:] :element-uid:}
// unsized vec ([T]) -> {[] :element-uid:}
// trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
// closure -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
// basic type -> {:name of the type:}
// tuple -> {tuple_(:param-uid:)*}
// struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
// enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
// enum variant -> {variant_:variant-name:_:enum-uid:}
// reference (&) -> {& :pointee-uid:}
// mut reference (&mut) -> {&mut :pointee-uid:}
// ptr (*) -> {* :pointee-uid:}
// mut ptr (*mut) -> {*mut :pointee-uid:}
// unique ptr (box) -> {box :pointee-uid:}
// @-ptr (@) -> {@ :pointee-uid:}
// sized vec ([T; x]) -> {[:size:] :element-uid:}
// unsized vec ([T]) -> {[] :element-uid:}
// trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
// closure -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
// :return-type-uid: : (:bounds:)*}
// function -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
// function -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
// :return-type-uid:}
// unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>}
// gc box -> {GC_BOX<:pointee-uid:>}
match self.type_to_unique_id.get(&type_).cloned() {
Some(unique_type_id) => return unique_type_id,
@ -202,7 +200,7 @@ impl<'tcx> TypeMap<'tcx> {
}
},
ty::ty_uniq(inner_type) => {
unique_type_id.push('~');
unique_type_id.push_str("box ");
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(&inner_type_id[..]);

View file

@ -1603,7 +1603,8 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
Some(i as usize)),
_ => {
span_err!(tcx.sess, ast_ty.span, E0249,
"expected constant expr for array length");
"expected constant integer expression \
for array length");
this.tcx().types.err
}
}

View file

@ -371,7 +371,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) {
// Read the inherent implementation candidates for this type from the
// metadata if necessary.
ty::populate_implementations_for_type_if_necessary(self.tcx(), def_id);
ty::populate_inherent_implementations_for_type_if_necessary(self.tcx(), def_id);
if let Some(impl_infos) = self.tcx().inherent_impls.borrow().get(&def_id) {
for &impl_def_id in &***impl_infos {

View file

@ -2458,7 +2458,7 @@ fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::
}
// determine the `self` type, using fresh variables for all variables
// declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
// declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>`
// would return ($0, $1) where $0 and $1 are freshly instantiated type
// variables.
pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,

View file

@ -16,13 +16,10 @@
// mappings. That mapping code resides here.
use metadata::csearch::{each_impl, get_impl_trait};
use metadata::csearch;
use middle::subst::{self, Subst};
use middle::ty::RegionEscape;
use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
use middle::ty::{MethodTraitItemId, TypeTraitItemId};
use middle::ty::{ParameterEnvironment, lookup_item_type};
use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
use middle::ty::{ty_param, TypeScheme, ty_ptr};
use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
@ -33,7 +30,6 @@ use middle::ty;
use CrateCtxt;
use middle::infer::InferCtxt;
use middle::infer::new_infer_ctxt;
use std::collections::HashSet;
use std::cell::RefCell;
use std::rc::Rc;
use syntax::ast::{Crate, DefId};
@ -130,11 +126,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
Rc::new((*v.borrow()).clone()));
}
// Bring in external crates. It's fine for this to happen after the
// coherence checks, because we ensure by construction that no errors
// can happen at link time.
self.add_external_crates();
// Populate the table of destructors. It might seem a bit strange to
// do this here, but it's actually the most convenient place, since
// the coherence tables contain the trait -> type mappings.
@ -267,11 +258,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
trait_def.record_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref);
}
fn get_self_type_for_implementation(&self, impl_did: DefId)
-> TypeScheme<'tcx> {
self.crate_context.tcx.tcache.borrow().get(&impl_did).unwrap().clone()
}
// Converts an implementation in the AST to a vector of items.
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
match item.node {
@ -313,66 +299,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
}
}
// External crate handling
fn add_external_impl(&self,
impls_seen: &mut HashSet<DefId>,
impl_def_id: DefId) {
let tcx = self.crate_context.tcx;
let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
impl_def_id);
// Make sure we don't visit the same implementation multiple times.
if !impls_seen.insert(impl_def_id) {
// Skip this one.
return
}
// Good. Continue.
let _ = lookup_item_type(tcx, impl_def_id);
let associated_traits = get_impl_trait(tcx, impl_def_id);
// Do a sanity check.
assert!(associated_traits.is_some());
// Record all the trait items.
if let Some(trait_ref) = associated_traits {
self.add_trait_impl(trait_ref, impl_def_id);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for item_def_id in &impl_items {
let impl_item = ty::impl_or_trait_item(tcx, item_def_id.def_id());
match impl_item {
ty::MethodTraitItem(ref method) => {
if let Some(source) = method.provided_source {
tcx.provided_method_sources
.borrow_mut()
.insert(item_def_id.def_id(), source);
}
}
_ => {}
}
}
tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
}
// Adds implementations and traits from external crates to the coherence
// info.
fn add_external_crates(&self) {
let mut impls_seen = HashSet::new();
let crate_store = &self.crate_context.tcx.sess.cstore;
crate_store.iter_crate_data(|crate_number, _crate_metadata| {
each_impl(crate_store, crate_number, |def_id| {
assert_eq!(crate_number, def_id.krate);
self.add_external_impl(&mut impls_seen, def_id)
})
})
}
//
// Destructors
//
@ -395,7 +321,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
}
let method_def_id = items[0];
let self_type = self.get_self_type_for_implementation(impl_did);
let self_type = ty::lookup_item_type(tcx, impl_did);
match self_type.ty.sty {
ty::ty_enum(type_def_id, _) |
ty::ty_struct(type_def_id, _) |
@ -451,7 +377,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
return
}
let self_type = self.get_self_type_for_implementation(impl_did);
let self_type = ty::lookup_item_type(tcx, impl_did);
debug!("check_implementations_of_copy: self_type={} (bound)",
self_type.repr(tcx));

View file

@ -48,14 +48,9 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
// check_for_overlapping_impls_of_trait() check, since that
// check can populate this table further with impls from other
// crates.
let trait_defs : Vec<&ty::TraitDef> = {
let d = self.tcx.trait_defs.borrow();
d.values().map(|&v|v).collect()
};
let trait_defs: Vec<_> = self.tcx.trait_defs.borrow().values().cloned().collect();
for trait_def in trait_defs {
// FIXME -- it seems like this method actually pushes
// duplicate impls onto the list
ty::populate_implementations_for_trait_if_necessary(
self.tcx,
trait_def.trait_ref.def_id);

View file

@ -46,6 +46,23 @@ enum variant, one of the fields was not provided. Each field should be specified
exactly once.
"##,
E0067: r##"
The left-hand side of an assignment operator must be an lvalue expression. An
lvalue expression represents a memory location and includes item paths (ie,
namespaced variables), dereferences, indexing expressions, and field references.
```
use std::collections::LinkedList;
// Good
let mut list = LinkedList::new();
// Bad: assignment to non-lvalue expression
LinkedList::new() += 1;
```
"##,
E0081: r##"
Enum discriminants are used to differentiate enum variants stored in memory.
This error indicates that the same value was used for two or more variants,
@ -119,6 +136,162 @@ construct an instance of the following type using only safe code:
```
enum Empty {}
```
"##,
E0131: r##"
It is not possible to define `main` with type parameters, or even with function
parameters. When `main` is present, it must take no arguments and return `()`.
"##,
E0132: r##"
It is not possible to declare type parameters on a function that has the `start`
attribute. Such a function must have the following type signature:
```
fn(isize, *const *const u8) -> isize
```
"##,
E0184: r##"
Explicitly implementing both Drop and Copy for a type is currently disallowed.
This feature can make some sense in theory, but the current implementation is
incorrect and can lead to memory unsafety (see [issue #20126][iss20126]), so
it has been disabled for now.
[iss20126]: https://github.com/rust-lang/rust/issues/20126
"##,
E0204: r##"
An attempt to implement the `Copy` trait for a struct failed because one of the
fields does not implement `Copy`. To fix this, you must implement `Copy` for the
mentioned field. Note that this may not be possible, as in the example of
```
struct Foo {
foo : Vec<u32>,
}
impl Copy for Foo { }
```
This fails because `Vec<T>` does not implement `Copy` for any `T`.
Here's another example that will fail:
```
#[derive(Copy)]
struct Foo<'a> {
ty: &'a mut bool,
}
```
This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
differs from the behavior for `&T`, which is always `Copy`).
"##,
E0205: r##"
An attempt to implement the `Copy` trait for an enum failed because one of the
variants does not implement `Copy`. To fix this, you must implement `Copy` for
the mentioned variant. Note that this may not be possible, as in the example of
```
enum Foo {
Bar(Vec<u32>),
Baz,
}
impl Copy for Foo { }
```
This fails because `Vec<T>` does not implement `Copy` for any `T`.
Here's another example that will fail:
```
#[derive(Copy)]
enum Foo<'a> {
Bar(&'a mut bool),
Baz
}
```
This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
differs from the behavior for `&T`, which is always `Copy`).
"##,
E0206: r##"
You can only implement `Copy` for a struct or enum. Both of the following
examples will fail, because neither `i32` (primitive type) nor `&'static Bar`
(reference to `Bar`) is a struct or enum:
```
type Foo = i32;
impl Copy for Foo { } // error
#[derive(Copy, Clone)]
struct Bar;
impl Copy for &'static Bar { } // error
```
"##,
E0243: r##"
This error indicates that not enough type parameters were found in a type or
trait.
For example, the `Foo` struct below is defined to be generic in `T`, but the
type parameter is missing in the definition of `Bar`:
```
struct Foo<T> { x: T }
struct Bar { x: Foo }
```
"##,
E0244: r##"
This error indicates that too many type parameters were found in a type or
trait.
For example, the `Foo` struct below has no type parameters, but is supplied
with two in the definition of `Bar`:
```
struct Foo { x: bool }
struct Bar<S, T> { x: Foo<S, T> }
```
"##,
E0249: r##"
This error indicates a constant expression for the array length was found, but
it was not an integer (signed or unsigned) expression.
Some examples of code that produces this error are:
```
const A: [u32; "hello"] = []; // error
const B: [u32; true] = []; // error
const C: [u32; 0.0] = []; // error
"##,
E0250: r##"
This means there was an error while evaluating the expression for the length of
a fixed-size array type.
Some examples of code that produces this error are:
```
// divide by zero in the length expression
const A: [u32; 1/0] = [];
// Rust currently will not evaluate the function `foo` at compile time
fn foo() -> usize { 12 }
const B: [u32; foo()] = [];
// it is an error to try to add `u8` and `f64`
use std::{f64, u8};
const C: [u32; u8::MAX + f64::EPSILON] = [];
```
"##
}
@ -133,23 +306,22 @@ register_diagnostics! {
E0030,
E0031,
E0033,
E0034,
E0035,
E0036,
E0038,
E0034, // multiple applicable methods in scope
E0035, // does not take type parameters
E0036, // incorrect number of type parameters given for this method
E0038, // cannot convert to a trait object because trait is not object-safe
E0040, // explicit use of destructor method
E0044,
E0045,
E0044, // foreign items may not have type parameters
E0045, // variadic function must have C calling convention
E0049,
E0050,
E0053,
E0055,
E0057,
E0055, // method has an incompatible type for trait
E0057, // method has an incompatible type for trait
E0059,
E0060,
E0061,
E0066,
E0067,
E0068,
E0069,
E0070,
@ -189,8 +361,6 @@ register_diagnostics! {
E0128,
E0129,
E0130,
E0131,
E0132,
E0141,
E0159,
E0163,
@ -204,7 +374,6 @@ register_diagnostics! {
E0178,
E0182,
E0183,
E0184,
E0185,
E0186,
E0187, // can't infer the kind of the closure
@ -226,12 +395,6 @@ register_diagnostics! {
E0202, // associated items are not allowed in inherent impls
E0203, // type parameter has more than one relaxed default bound,
// and only one is supported
E0204, // trait `Copy` may not be implemented for this type; field
// does not implement `Copy`
E0205, // trait `Copy` may not be implemented for this type; variant
// does not implement `copy`
E0206, // trait `Copy` may not be implemented for this type; type is
// not a structure or enumeration
E0207, // type parameter is not constrained by the impl trait, self type, or predicate
E0208,
E0209, // builtin traits can only be implemented on structs or enums
@ -268,14 +431,10 @@ register_diagnostics! {
E0240,
E0241,
E0242, // internal error looking up a definition
E0243, // wrong number of type arguments
E0244, // wrong number of type arguments
E0245, // not a trait
E0246, // illegal recursive type
E0247, // found module name used as a type
E0248, // found value name used as a type
E0249, // expected constant expr for array length
E0250, // expected constant expr for array length
E0318, // can't create default impls for traits outside their crates
E0319, // trait impls for defaulted traits allowed just for structs/enums
E0320, // recursive overflow during dropck

View file

@ -178,8 +178,8 @@
//! further that for whatever reason I specifically supply the value of
//! `String` for the type parameter `T`:
//!
//! let mut vector = ~["string", ...];
//! convertAll::<int, String>(v);
//! let mut vector = vec!["string", ...];
//! convertAll::<int, String>(vector);
//!
//! Is this legal? To put another way, can we apply the `impl` for
//! `Object` to the type `String`? The answer is yes, but to see why

View file

@ -221,7 +221,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
pub fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
did: ast::DefId) -> Vec<clean::Item> {
ty::populate_implementations_for_type_if_necessary(tcx, did);
ty::populate_inherent_implementations_for_type_if_necessary(tcx, did);
let mut impls = Vec::new();
match tcx.inherent_impls.borrow().get(&did) {

View file

@ -897,7 +897,7 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
}
}
// maybe use a Generic enum and use ~[Generic]?
// maybe use a Generic enum and use Vec<Generic>?
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub struct Generics {
pub lifetimes: Vec<Lifetime>,

View file

@ -905,6 +905,8 @@ impl DocFolder for Cache {
// Index this method for searching later on
if let Some(ref s) = item.name {
let (parent, is_method) = match item.inner {
clean::AssociatedTypeItem(..) |
clean::AssociatedConstItem(..) |
clean::TyMethodItem(..) |
clean::StructFieldItem(..) |
clean::VariantItem(..) => {
@ -1862,6 +1864,17 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
try!(write!(w, "</div>"));
}
if !consts.is_empty() {
try!(write!(w, "
<h2 id='associated-const'>Associated Constants</h2>
<div class='methods'>
"));
for t in &consts {
try!(trait_item(w, *t));
}
try!(write!(w, "</div>"));
}
// Output the documentation for each function individually
if !required.is_empty() {
try!(write!(w, "

View file

@ -34,7 +34,8 @@
"macro",
"primitive",
"associatedtype",
"constant"];
"constant",
"associatedconstant"];
$('.js-only').removeClass('js-only');

View file

@ -916,6 +916,24 @@ impl<K, V, S> HashMap<K, V, S>
}
/// Gets the given key's corresponding entry in the map for in-place manipulation.
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
///
/// let mut letters = HashMap::new();
///
/// for ch in "a short treatise on fungi".chars() {
/// let counter = letters.entry(ch).or_insert(0);
/// *counter += 1;
/// }
///
/// assert_eq!(letters[&'s'], 2);
/// assert_eq!(letters[&'t'], 3);
/// assert_eq!(letters[&'u'], 1);
/// assert_eq!(letters.get(&'y'), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn entry(&mut self, key: K) -> Entry<K, V> {
// Gotta resize now.

View file

@ -844,7 +844,7 @@ impl fmt::Display for CharsError {
/// An iterator over the contents of an instance of `BufRead` split on a
/// particular byte.
///
/// See `BufReadExt::split` for more information.
/// See `BufRead::split` for more information.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Split<B> {
buf: B,
@ -873,7 +873,7 @@ impl<B: BufRead> Iterator for Split<B> {
/// An iterator over the lines of an instance of `BufRead` split on a newline
/// byte.
///
/// See `BufReadExt::lines` for more information.
/// See `BufRead::lines` for more information.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Lines<B> {
buf: B,

View file

@ -1199,7 +1199,7 @@ impl Into<OsString> for PathBuf {
/// absolute, and so on. More details about the overall approach can be found in
/// the module documentation.
///
/// This is an *unsized* type, meaning that it must always be used with behind a
/// This is an *unsized* type, meaning that it must always be used behind a
/// pointer like `&` or `Box`.
///
/// # Examples
@ -1449,6 +1449,8 @@ impl Path {
/// Determines whether `base` is a prefix of `self`.
///
/// Only considers whole path components to match.
///
/// # Examples
///
/// ```
@ -1457,6 +1459,8 @@ impl Path {
/// let path = Path::new("/etc/passwd");
///
/// assert!(path.starts_with("/etc"));
///
/// assert!(!path.starts_with("/e"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
@ -1465,6 +1469,8 @@ impl Path {
/// Determines whether `child` is a suffix of `self`.
///
/// Only considers whole path components to match.
///
/// # Examples
///
/// ```

View file

@ -85,6 +85,8 @@ pub struct LocalKey<T> {
}
/// Declare a new thread local storage key of type `std::thread::LocalKey`.
///
/// See [LocalKey documentation](thread/struct.LocalKey.html) for more information.
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable]

View file

@ -66,6 +66,8 @@ pub struct ScopedKey<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> }
///
/// This macro declares a `static` item on which methods are used to get and
/// set the value stored within.
///
/// See [ScopedKey documentation](thread/struct.ScopedKey.html) for more information.
#[macro_export]
#[allow_internal_unstable]
macro_rules! scoped_thread_local {

View file

@ -904,8 +904,8 @@ impl<'a> MethodDef<'a> {
nonself_args: &[P<Expr>])
-> P<Expr> {
let mut raw_fields = Vec::new(); // ~[[fields of self],
// [fields of next Self arg], [etc]]
let mut raw_fields = Vec::new(); // Vec<[fields of self],
// [fields of next Self arg], [etc]>
let mut patterns = Vec::new();
for i in 0..self_args.len() {
let struct_path= cx.path(DUMMY_SP, vec!( type_ident ));

View file

@ -1719,7 +1719,7 @@ mod tests {
// induced by visit. Each of these arrays contains a list of indexes,
// interpreted as the varrefs in the varref traversal that this binding
// should match. So, for instance, in a program with two bindings and
// three varrefs, the array ~[~[1,2],~[0]] would indicate that the first
// three varrefs, the array [[1, 2], [0]] would indicate that the first
// binding should match the second two varrefs, and the second binding
// should match the first varref.
//

View file

@ -109,15 +109,6 @@ pub enum PathParsingMode {
LifetimeAndTypesWithColons,
}
/// How to parse a qualified path, whether to allow trailing parameters.
#[derive(Copy, Clone, PartialEq)]
pub enum QPathParsingMode {
/// No trailing parameters, e.g. `<T as Trait>::Item`
NoParameters,
/// Optional parameters, e.g. `<T as Trait>::item::<'a, U>`
MaybeParameters,
}
/// How to parse a bound, whether to allow bound modifiers such as `?`.
#[derive(Copy, Clone, PartialEq)]
pub enum BoundParsingMode {
@ -1359,7 +1350,7 @@ impl<'a> Parser<'a> {
} else if try!(self.eat_lt()) {
let (qself, path) =
try!(self.parse_qualified_path(QPathParsingMode::NoParameters));
try!(self.parse_qualified_path(NoTypesAllowed));
TyPath(Some(qself), path)
} else if self.check(&token::ModSep) ||
@ -1578,7 +1569,7 @@ impl<'a> Parser<'a> {
// QUALIFIED PATH `<TYPE [as TRAIT_REF]>::IDENT[::<PARAMS>]`
// Assumes that the leading `<` has been parsed already.
pub fn parse_qualified_path(&mut self, mode: QPathParsingMode)
pub fn parse_qualified_path(&mut self, mode: PathParsingMode)
-> PResult<(QSelf, ast::Path)> {
let self_type = try!(self.parse_ty_sum());
let mut path = if try!(self.eat_keyword(keywords::As)) {
@ -1599,29 +1590,18 @@ impl<'a> Parser<'a> {
try!(self.expect(&token::Gt));
try!(self.expect(&token::ModSep));
let item_name = try!(self.parse_ident());
let parameters = match mode {
QPathParsingMode::NoParameters => ast::PathParameters::none(),
QPathParsingMode::MaybeParameters => {
if try!(self.eat(&token::ModSep)) {
try!(self.expect_lt());
// Consumed `item::<`, go look for types
let (lifetimes, types, bindings) =
try!(self.parse_generic_values_after_lt());
ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: OwnedSlice::from_vec(types),
bindings: OwnedSlice::from_vec(bindings),
})
} else {
ast::PathParameters::none()
}
let segments = match mode {
LifetimeAndTypesWithoutColons => {
try!(self.parse_path_segments_without_colons())
}
LifetimeAndTypesWithColons => {
try!(self.parse_path_segments_with_colons())
}
NoTypesAllowed => {
try!(self.parse_path_segments_without_types())
}
};
path.segments.push(ast::PathSegment {
identifier: item_name,
parameters: parameters
});
path.segments.extend(segments);
if path.segments.len() == 1 {
path.span.lo = self.last_span.lo;
@ -2096,7 +2076,7 @@ impl<'a> Parser<'a> {
if try!(self.eat_lt()){
let (qself, path) =
try!(self.parse_qualified_path(QPathParsingMode::MaybeParameters));
try!(self.parse_qualified_path(LifetimeAndTypesWithColons));
return Ok(self.mk_expr(lo, hi, ExprPath(Some(qself), path)));
}
@ -3176,7 +3156,7 @@ impl<'a> Parser<'a> {
let (qself, path) = if try!(self.eat_lt()) {
// Parse a qualified path
let (qself, path) =
try!(self.parse_qualified_path(QPathParsingMode::NoParameters));
try!(self.parse_qualified_path(NoTypesAllowed));
(Some(qself), path)
} else {
// Parse an unqualified path
@ -3270,7 +3250,7 @@ impl<'a> Parser<'a> {
let (qself, path) = if try!(self.eat_lt()) {
// Parse a qualified path
let (qself, path) =
try!(self.parse_qualified_path(QPathParsingMode::NoParameters));
try!(self.parse_qualified_path(NoTypesAllowed));
(Some(qself), path)
} else {
// Parse an unqualified path

View file

@ -312,7 +312,7 @@ impl<'a> Printer<'a> {
self.token[self.right] = t;
}
pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
debug!("pp ~[{},{}]", self.left, self.right);
debug!("pp Vec<{},{}>", self.left, self.right);
match token {
Token::Eof => {
if !self.scan_stack_empty {
@ -329,7 +329,7 @@ impl<'a> Printer<'a> {
self.left = 0;
self.right = 0;
} else { self.advance_right(); }
debug!("pp Begin({})/buffer ~[{},{}]",
debug!("pp Begin({})/buffer Vec<{},{}>",
b.offset, self.left, self.right);
self.token[self.right] = token;
self.size[self.right] = -self.right_total;
@ -339,10 +339,10 @@ impl<'a> Printer<'a> {
}
Token::End => {
if self.scan_stack_empty {
debug!("pp End/print ~[{},{}]", self.left, self.right);
debug!("pp End/print Vec<{},{}>", self.left, self.right);
self.print(token, 0)
} else {
debug!("pp End/buffer ~[{},{}]", self.left, self.right);
debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
self.advance_right();
self.token[self.right] = token;
self.size[self.right] = -1;
@ -358,7 +358,7 @@ impl<'a> Printer<'a> {
self.left = 0;
self.right = 0;
} else { self.advance_right(); }
debug!("pp Break({})/buffer ~[{},{}]",
debug!("pp Break({})/buffer Vec<{},{}>",
b.offset, self.left, self.right);
self.check_stack(0);
let right = self.right;
@ -370,11 +370,11 @@ impl<'a> Printer<'a> {
}
Token::String(s, len) => {
if self.scan_stack_empty {
debug!("pp String('{}')/print ~[{},{}]",
debug!("pp String('{}')/print Vec<{},{}>",
s, self.left, self.right);
self.print(Token::String(s, len), len)
} else {
debug!("pp String('{}')/buffer ~[{},{}]",
debug!("pp String('{}')/buffer Vec<{},{}>",
s, self.left, self.right);
self.advance_right();
self.token[self.right] = Token::String(s, len);
@ -386,7 +386,7 @@ impl<'a> Printer<'a> {
}
}
pub fn check_stream(&mut self) -> io::Result<()> {
debug!("check_stream ~[{}, {}] with left_total={}, right_total={}",
debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}",
self.left, self.right, self.left_total, self.right_total);
if self.right_total - self.left_total > self.space {
debug!("scan window is {}, longer than space on line ({})",
@ -446,7 +446,7 @@ impl<'a> Printer<'a> {
assert!((self.right != self.left));
}
pub fn advance_left(&mut self) -> io::Result<()> {
debug!("advance_left ~[{},{}], sizeof({})={}", self.left, self.right,
debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
self.left, self.size[self.left]);
let mut left_size = self.size[self.left];

View file

@ -259,8 +259,8 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn> ) {
// This will panic (intentionally) when fed any dynamic tests, because
// it is copying the static values out into a dynamic vector and cannot
// copy dynamic values. It is doing this because from this point on
// a ~[TestDescAndFn] is used in order to effect ownership-transfer
// semantics into parallel test runners, which in turn requires a ~[]
// a Vec<TestDescAndFn> is used in order to effect ownership-transfer
// semantics into parallel test runners, which in turn requires a Vec<>
// rather than a &[].
pub fn test_main_static(args: env::Args, tests: &[TestDescAndFn]) {
let args = args.collect::<Vec<_>>();

View file

@ -0,0 +1,27 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
#![feature(no_std)]
#![no_std]
// This tests that conflicting imports shows both `use` lines
// when reporting the error.
mod sub1 {
fn foo() {} // implementation 1
}
mod sub2 {
fn foo() {} // implementation 2
}
use sub1::foo; //~ NOTE previous import of `foo` here
use sub2::foo; //~ ERROR a value named `foo` has already been imported in this module [E0252]
fn main() {}

View file

@ -0,0 +1,25 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
trait Foo {
fn answer(self);
}
struct NoData<T>;
//~^ ERROR: parameter `T` is never used
impl<T> Foo for T where NoData<T>: Foo {
//~^ ERROR: overflow evaluating the requirement
fn answer(self) {
let val: NoData<T> = NoData;
}
}
fn main() {}

View file

@ -37,7 +37,7 @@ fn test<'a,T,U:Copy>(_: &'a isize) {
assert_copy::<&'static mut isize>(); //~ ERROR `core::marker::Copy` is not implemented
assert_copy::<&'a mut isize>(); //~ ERROR `core::marker::Copy` is not implemented
// ~ pointers are not ok
// owned pointers are not ok
assert_copy::<Box<isize>>(); //~ ERROR `core::marker::Copy` is not implemented
assert_copy::<String>(); //~ ERROR `core::marker::Copy` is not implemented
assert_copy::<Vec<isize> >(); //~ ERROR `core::marker::Copy` is not implemented

View file

@ -13,7 +13,7 @@
// ignore-test
fn main() {
let args : ~[String] = ::std::os::args();
let args : Vec<String> = ::std::os::args();
::std::io::println(args[0]);
}
@ -25,6 +25,6 @@ fn main() {
// compile-flags:-g
// gdb-command:list
// gdb-check:1[...]fn main() {
// gdb-check:2[...]let args : ~[String] = ::std::os::args();
// gdb-check:2[...]let args : Vec<String> = ::std::os::args();
// gdb-check:3[...]::std::io::println(args[0]);
// gdb-check:4[...]}

View file

@ -0,0 +1,55 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
use std::mem::size_of;
// The main point of this test is to ensure that we can parse and resolve
// associated items on associated types.
trait Foo {
type U;
}
trait Bar {
// Note 1: Chains of associated items in a path won't type-check.
// Note 2: Associated consts can't depend on type parameters or `Self`,
// which are the only types that an associated type can be referenced on for
// now, so we can only test methods.
fn method() -> u32;
fn generic_method<T>() -> usize;
}
struct MyFoo;
struct MyBar;
impl Foo for MyFoo {
type U = MyBar;
}
impl Bar for MyBar {
fn method() -> u32 {
2u32
}
fn generic_method<T>() -> usize {
size_of::<T>()
}
}
fn foo<T>()
where T: Foo,
T::U: Bar,
{
assert_eq!(2u32, <T as Foo>::U::method());
assert_eq!(8usize, <T as Foo>::U::generic_method::<f64>());
}
fn main() {
foo::<MyFoo>();
}

View file

@ -20,7 +20,7 @@ struct F { field: isize }
pub fn main() {
/*foo(1);
foo("hi".to_string());
foo(~[1, 2, 3]);
foo(vec![1, 2, 3]);
foo(F{field: 42});
foo((1, 2));
foo(@1);*/

View file

@ -0,0 +1,16 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
// exec-env:RUST_LOG=rustc::middle=debug
fn main() {
let b = 1isize;
println!("{}", b);
}

View file

@ -0,0 +1,20 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
pub trait Data { fn doit(&self) {} }
impl<T> Data for T {}
pub trait UnaryLogic { type D: Data; }
impl UnaryLogic for () { type D = i32; }
pub fn crashes<T: UnaryLogic>(t: T::D) {
t.doit();
}
fn main() { crashes::<()>(0); }

View file

@ -32,10 +32,6 @@ fn check_strs(actual: &str, expected: &str) -> bool
pub fn main()
{
// assert!(check_strs(fmt!("%?", Text(@"foo".to_string())), "Text(@~\"foo\")"));
// assert!(check_strs(fmt!("%?", ETag(@~["foo".to_string()], @"bar".to_string())),
// "ETag(@~[ ~\"foo\" ], @~\"bar\")"));
let t = Token::Text("foo".to_string());
let u = Token::Section(vec!["alpha".to_string()],
true,

View file

@ -22,8 +22,8 @@ use std::io::{ReaderUtil,WriterUtil};
enum Result {
Nil,
Int(isize),
Data(~[u8]),
List(~[Result]),
Data(Vec<u8>),
List(Vec<Result>),
Error(String),
Status(String)
}
@ -35,7 +35,7 @@ fn parse_data(len: usize, io: @io::Reader) -> Result {
assert_eq!(bytes.len(), len);
Data(bytes)
} else {
Data(~[])
Data(vec![])
};
assert_eq!(io.read_char(), '\r');
assert_eq!(io.read_char(), '\n');
@ -43,7 +43,7 @@ fn parse_data(len: usize, io: @io::Reader) -> Result {
}
fn parse_list(len: usize, io: @io::Reader) -> Result {
let mut list: ~[Result] = ~[];
let mut list: Vec<Result> = vec![];
for _ in 0..len {
let v = match io.read_char() {
'$' => parse_bulk(io),
@ -72,7 +72,7 @@ fn parse_multi(io: @io::Reader) -> Result {
match from_str::<isize>(chop(io.read_line())) {
None => panic!(),
Some(-1) => Nil,
Some(0) => List(~[]),
Some(0) => List(vec![]),
Some(len) if len >= 0 => parse_list(len as usize, io),
Some(_) => panic!()
}
@ -96,7 +96,7 @@ fn parse_response(io: @io::Reader) -> Result {
}
}
fn cmd_to_string(cmd: ~[String]) -> String {
fn cmd_to_string(cmd: Vec<String>) -> String {
let mut res = "*".to_string();
res.push_str(cmd.len().to_string());
res.push_str("\r\n");
@ -107,7 +107,7 @@ fn cmd_to_string(cmd: ~[String]) -> String {
res
}
fn query(cmd: ~[String], sb: TcpSocketBuf) -> Result {
fn query(cmd: Vec<String>, sb: TcpSocketBuf) -> Result {
let cmd = cmd_to_string(cmd);
//println!("{}", cmd);
sb.write_str(cmd);
@ -115,7 +115,7 @@ fn query(cmd: ~[String], sb: TcpSocketBuf) -> Result {
res
}
fn query2(cmd: ~[String]) -> Result {
fn query2(cmd: Vec<String>) -> Result {
let _cmd = cmd_to_string(cmd);
io::with_str_reader("$3\r\nXXX\r\n".to_string())(|sb| {
let res = parse_response(@sb as @io::Reader);

View file

@ -0,0 +1,60 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
// compile-flags: -C debug-assertions
#![feature(core)]
use std::slice;
fn foo<T>(v: &[T]) -> Option<&[T]> {
let mut it = v.iter();
for _ in 0..5 {
let _ = it.next();
}
Some(it.as_slice())
}
fn foo_mut<T>(v: &mut [T]) -> Option<&mut [T]> {
let mut it = v.iter_mut();
for _ in 0..5 {
let _ = it.next();
}
Some(it.into_slice())
}
pub fn main() {
// In a slice of zero-size elements the pointer is meaningless.
// Ensure iteration still works even if the pointer is at the end of the address space.
let slice: &[()] = unsafe { slice::from_raw_parts(-5isize as *const (), 10) };
assert_eq!(slice.len(), 10);
assert_eq!(slice.iter().count(), 10);
// .nth() on the iterator should also behave correctly
let mut it = slice.iter();
assert!(it.nth(5).is_some());
assert_eq!(it.count(), 4);
// Converting Iter to a slice should never have a null pointer
assert!(foo(slice).is_some());
// Test mutable iterators as well
let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) };
assert_eq!(slice.len(), 10);
assert_eq!(slice.iter_mut().count(), 10);
{
let mut it = slice.iter_mut();
assert!(it.nth(5).is_some());
assert_eq!(it.count(), 4);
}
assert!(foo_mut(slice).is_some())
}

View file

@ -13,6 +13,7 @@
pub trait Foo {
// @has assoc_consts/trait.Foo.html '//*[@class="rust trait"]' \
// 'const FOO: usize;'
// @has - '//*[@id="associatedconstant.FOO"]' 'const FOO'
const FOO: usize;
}