From 84bc74e54a2d46f87c4205b99e78c2ce3ef9c881 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Fri, 5 Oct 2012 20:18:19 -0400 Subject: [PATCH 001/292] update Kate syntax file with latest keywords and types --- src/etc/kate/rust.xml | 57 +++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 38 deletions(-) diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml index b93479677eea..16a205ddc161 100644 --- a/src/etc/kate/rust.xml +++ b/src/etc/kate/rust.xml @@ -1,6 +1,6 @@ - + fn @@ -9,59 +9,39 @@ type - alt - again as assert break - check - claim const copy do drop else + enum export extern - f16 - f80 - f128 fail for if impl - import - in let log loop - m32 - m64 - m128 match mod - module move mut - new - of - owned priv pub pure - ret + ref return - to - unchecked + static + struct + trait unsafe use while - with - mod - trait - class - struct - enum bool @@ -80,8 +60,9 @@ float char str - option - either + Either + Option + Result c_float @@ -121,16 +102,16 @@ true false - some - none - left - right - ok - err - success - failure - cons - nil + Some + None + Left + Right + Ok + Err + Success + Failure + Cons + Nil EXIT_FAILURE From 035cfcbe7218018c1bab29a987ee1152ccd1dcf7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 15:47:57 -0700 Subject: [PATCH 002/292] docs: Clean up trait and module examples --- doc/tutorial.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index bf262105f6e4..1b857bae1eb2 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -2044,13 +2044,11 @@ However, consider this function: # type Circle = int; type Rectangle = int; # impl int: Drawable { fn draw() {} } # fn new_circle() -> int { 1 } - trait Drawable { fn draw(); } fn draw_all(shapes: ~[T]) { for shapes.each |shape| { shape.draw(); } } - # let c: Circle = new_circle(); # draw_all(~[c]); ~~~~ @@ -2062,7 +2060,7 @@ needed, a trait name can alternately be used as a type. ~~~~ # trait Drawable { fn draw(); } -fn draw_all(shapes: ~[@Drawable]) { +fn draw_all(shapes: &[@Drawable]) { for shapes.each |shape| { shape.draw(); } } ~~~~ @@ -2077,7 +2075,7 @@ to cast a value to a trait type: # trait Drawable { fn draw(); } # fn new_circle() -> Circle { 1 } # fn new_rectangle() -> Rectangle { true } -# fn draw_all(shapes: ~[Drawable]) {} +# fn draw_all(shapes: &[@Drawable]) {} impl @Circle: Drawable { fn draw() { ... } } @@ -2085,7 +2083,7 @@ impl @Rectangle: Drawable { fn draw() { ... } } let c: @Circle = @new_circle(); let r: @Rectangle = @new_rectangle(); -draw_all(~[c as @Drawable, r as @Drawable]); +draw_all(&[c as @Drawable, r as @Drawable]); ~~~~ Note that, like strings and vectors, trait types have dynamic size @@ -2130,10 +2128,9 @@ explicitly import it, you must refer to it by its long name, `farm::chicken`. ~~~~ -#[legacy_exports] mod farm { - fn chicken() -> ~str { ~"cluck cluck" } - fn cow() -> ~str { ~"mooo" } + pub fn chicken() -> ~str { ~"cluck cluck" } + pub fn cow() -> ~str { ~"mooo" } } fn main() { io::println(farm::chicken()); From f5c95de212d7851c7f8788a328455ed381e38978 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 20:23:38 -0700 Subject: [PATCH 003/292] docs: Edit the into bullets --- doc/tutorial.md | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 1b857bae1eb2..37b0b722eaa8 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -15,21 +15,17 @@ As a multi-paradigm language, Rust supports writing code in procedural, functional and object-oriented styles. Some of its pleasant high-level features include: -* **Pattern matching and algebraic data types (enums).** As - popularized by functional languages, pattern matching on ADTs - provides a compact and expressive way to encode program logic. -* **Type inference.** Type annotations on local variable - declarations are optional. -* **Task-based concurrency.** Rust uses lightweight tasks that do - not share memory. -* **Higher-order functions.** Rust's efficient and flexible closures - are heavily relied on to provide iteration and other control - structures -* **Parametric polymorphism (generics).** Functions and types can be - parameterized over type variables with optional trait-based type - constraints. -* **Trait polymorphism.** Rust's type system features a unique - combination of type classes and object-oriented interfaces. +* **Type inference.** Type annotations on local variable declarations + are optional. +* **Safe task-based concurrency.** Rust's lightweight tasks do not share + memory and communicate through messages. +* **Higher-order functions.** Efficient and flexible closures provide + iteration and other control structures +* **Pattern matching and algebraic data types.** Pattern matching on + Rust's enums is a compact and expressive way to encode program + logic. +* **Polymorphism.** Rust has type-parameric functions and + types, type classes and OO-style interfaces. ## Scope From d5d774124730ee363620c6e4ec5bf65deea2385c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 22:23:16 -0700 Subject: [PATCH 004/292] Overhaul mods and crates section of tutorial --- doc/lib/codemirror-rust.js | 2 +- doc/tutorial.md | 317 ++++++++++++++++++------------------- 2 files changed, 155 insertions(+), 164 deletions(-) diff --git a/doc/lib/codemirror-rust.js b/doc/lib/codemirror-rust.js index 02f2c603955f..727882d30994 100644 --- a/doc/lib/codemirror-rust.js +++ b/doc/lib/codemirror-rust.js @@ -9,7 +9,7 @@ CodeMirror.defineMode("rust", function() { "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op", "claim": "op", "extern": "ignore", "unsafe": "ignore", "import": "else-style", "export": "else-style", "copy": "op", "log": "op", - "use": "op", "self": "atom" + "use": "op", "self": "atom", "pub": "atom", "priv": "atom" }; var typeKeywords = function() { var keywords = {"fn": "fn"}; diff --git a/doc/tutorial.md b/doc/tutorial.md index 37b0b722eaa8..f73ddd1b4c46 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -31,7 +31,7 @@ pleasant high-level features include: This is an introductory tutorial for the Rust programming language. It covers the fundamentals of the language, including the syntax, the -type system and memory model, and generics. [Additional +type system and memory model, generics, and modules. [Additional tutorials](#what-next) cover specific language features in greater depth. @@ -2113,61 +2113,123 @@ This usage of traits is similar to Java interfaces. # Modules and crates -The Rust namespace is divided into modules. Each source file starts -with its own module. - -## Local modules - -The `mod` keyword can be used to open a new, local module. In the -example below, `chicken` lives in the module `farm`, so, unless you -explicitly import it, you must refer to it by its long name, -`farm::chicken`. +The Rust namespace is arranged in a hierarchy of modules. Each source +(.rs) file represents a single module and may in turn contain +additional modules. ~~~~ mod farm { pub fn chicken() -> ~str { ~"cluck cluck" } pub fn cow() -> ~str { ~"mooo" } } + fn main() { io::println(farm::chicken()); } ~~~~ -Modules can be nested to arbitrary depth. +The contents of modules can be imported into the current scope +with the `use` keyword, optionally giving it an alias. `use` +may appear at the beginning of crates, `mod`s, `fn`s, and other +blocks. + +~~~ +# mod farm { pub fn chicken() { } } +# fn main() { +// Bring `chicken` into scope +use farm::chicken; + +fn chicken_farmer() { + // The same, but name it `my_chicken` + use my_chicken = farm::chicken; + ... +} +# } +~~~ + +These farm animal functions have a new keyword, `pub`, attached to +them. This is a visibility modifier that allows item to be accessed +outside of the module in which they are declared, using `::`, as in +`farm::chicken`. Items, like `fn`, `struct`, etc. are private by +default. + +Visibility restrictions in Rust exist only at module boundaries. This +is quite different from most object-oriented languages that also enforce +restrictions on objects themselves. That's not to say that Rust doesn't +support encapsulation - both struct fields and methods can be private - +but it is at the module level, not the class level. Note that fields +and methods are _public_ by default. + +~~~ +mod farm { +# pub fn make_me_a_farm() -> farm::Farm { farm::Farm { chickens: ~[], cows: ~[], farmer: Human(0) } } + pub struct Farm { + priv mut chickens: ~[Chicken], + priv mut cows: ~[Cow], + farmer: Human + } + + // Note - visibility modifiers on impls currently have no effect + impl Farm { + priv fn feed_chickens() { ... } + priv fn feed_cows() { ... } + fn add_chicken(c: Chicken) { ... } + } + + pub fn feed_animals(farm: &Farm) { + farm.feed_chickens(); + farm.feed_cows(); + } +} + +fn main() { + let f = make_me_a_farm(); + f.add_chicken(make_me_a_chicken()); + farm::feed_animals(&f); + f.farmer.rest(); +} +# type Chicken = int; +# type Cow = int; +# enum Human = int; +# fn make_me_a_farm() -> farm::Farm { farm::make_me_a_farm() } +# fn make_me_a_chicken() -> Chicken { 0 } +# impl Human { fn rest() { } } +~~~ ## Crates -The unit of independent compilation in Rust is the crate. Libraries -tend to be packaged as crates, and your own programs may consist of -one or more crates. +The unit of independent compilation in Rust is the crate - rustc +compiles a single crate at a time, from which it produces either a +library or executable. When compiling a single `.rs` file, the file acts as the whole crate. You can compile it with the `--lib` compiler switch to create a shared library, or without, provided that your file contains a `fn main` somewhere, to create an executable. -It is also possible to include multiple files in a crate. For this -purpose, you create a `.rc` crate file, which references any number of -`.rs` code files. A crate file could look like this: +Larger crates typically span multiple files and are compiled from +a crate (.rc) file. Crate files contain their own syntax for loading +modules from .rs files and typically include metadata about the crate. -~~~~ {.ignore} +~~~~ { .xfail-test } #[link(name = "farm", vers = "2.5", author = "mjh")]; #[crate_type = "lib"]; + mod cow; mod chicken; mod horse; ~~~~ Compiling this file will cause `rustc` to look for files named -`cow.rs`, `chicken.rs`, `horse.rs` in the same directory as the `.rc` -file, compile them all together, and, depending on the presence of the -`crate_type = "lib"` attribute, output a shared library or an executable. -(If the line `#[crate_type = "lib"];` was omitted, `rustc` would create an -executable.) +`cow.rs`, `chicken.rs`, and `horse.rs` in the same directory as the +`.rc` file, compile them all together, and, based on the presence of +the `crate_type = "lib"` attribute, output a shared library or an +executable. (If the line `#[crate_type = "lib"];` was omitted, +`rustc` would create an executable.) -The `#[link(...)]` part provides meta information about the module, -which other crates can use to load the right module. More about that -later. +The `#[link(...)]` attribute provides meta information about the +module, which other crates can use to load the right module. More +about that later. To have a nested directory structure for your source files, you can nest mods in your `.rc` file: @@ -2184,56 +2246,65 @@ The compiler will now look for `poultry/chicken.rs` and and `poultry::turkey`. You can also provide a `poultry.rs` to add content to the `poultry` module itself. -The compiler then builds the crate as a platform-specific shared library or -executable which can be distributed. +When compiling .rc files, if rustc finds a .rs file with the same +name, then that .rs file provides the top-level content of the crate. + +~~~ {.xfail-test} +// foo.rc +#[link(name = "foo", vers="1.0")]; + +mod bar; +~~~ + +~~~ {.xfail-test} +// foo.rs +fn main() { bar::baz(); } +~~~ + +> ***Note***: The way rustc looks for .rs files to pair with .rc +> files is a major source of confusion and will change. It's likely +> that the crate and source file grammars will merge. + +> ***Note***: The way that directory modules are handled will also +> change. The code for directory modules currently lives in a .rs +> file with the same name as the directory, _next to_ the directory. +> A new scheme will make that file live _inside_ the directory. ## Using other crates -Having compiled a crate that contains the `#[crate_type = "lib"]` -attribute, you can use it in another crate with a `use` -directive. We've already seen `extern mod std` in several of the -examples, which loads in the [standard library][std]. +Having compiled a crate into a library you can use it in another crate +with an `extern mod` directive. `extern mod` can appear at the top of +a crate file or at the top of modules. It will cause the compiler to +look in the library search path (which you can extend with `-L` +switch) for a compiled Rust library with the right name, then add a +module with that crate's name into the local scope. -[std]: http://doc.rust-lang.org/doc/std/index/General.html +For example, `extern mod std` links the [standard library]. -`use` directives can appear in a crate file, or at the top level of a -single-file `.rs` crate. They will cause the compiler to search its -library search path (which you can extend with `-L` switch) for a Rust -crate library with the right name. +[standard library]: std/index.html -It is possible to provide more specific information when using an -external crate. - -~~~~ {.ignore} -extern mod myfarm (name = "farm", vers = "2.7"); -~~~~ - -When a comma-separated list of name/value pairs is given after `use`, -these are matched against the attributes provided in the `link` +When a comma-separated list of name/value pairs is given after `extern +mod`, these are matched against the attributes provided in the `link` attribute of the crate file, and a crate is only used when the two match. A `name` value can be given to override the name used to search -for the crate. So the above would import the `farm` crate under the -local name `myfarm`. +for the crate. Our example crate declared this set of `link` attributes: -~~~~ {.ignore} +~~~~ {.xfail-test} #[link(name = "farm", vers = "2.5", author = "mjh")]; ~~~~ -The version does not match the one provided in the `use` directive, so -unless the compiler can find another crate with the right version -somewhere, it will complain that no matching crate was found. +Which can then be linked with any (or all) of the following: -## The core library +~~~~ {.xfail-test} +extern mod farm; +extern mod my_farm (name = "farm", vers = "2.5"); +extern mod my_auxiliary_farm (name = "farm", author = "mjh"); +~~~~ -A set of basic library routines, mostly related to built-in datatypes -and the task system, are always implicitly linked and included in any -Rust program. - -This library is documented [here][core]. - -[core]: core/index.html +If any of the requested metadata does not match then the crate +will not be compiled successfully. ## A minimal example @@ -2246,7 +2317,7 @@ these two files: fn explore() -> ~str { ~"world" } ~~~~ -~~~~ {.ignore} +~~~~ {.xfail-test} // main.rs extern mod world; fn main() { io::println(~"hello " + world::explore()); } @@ -2261,113 +2332,33 @@ Now compile and run like this (adjust to your platform if necessary): "hello world" ~~~~ -## Importing +Notice that the library produced contains the version in the filename +as well as an inscrutable string of alphanumerics. These are both +part of Rust's library versioning scheme. The alphanumerics are +a hash representing the crate metadata. -When using identifiers from other modules, it can get tiresome to -qualify them with the full module path every time (especially when -that path is several modules deep). Rust allows you to import -identifiers at the top of a file, module, or block. +## The core library -~~~~ -extern mod std; -use io::println; -fn main() { - println(~"that was easy"); -} -~~~~ +The Rust [core] library acts as the language runtime and contains +required memory management and task scheduling code as well as a +number of modules necessary for effective usage of the primitive +types. Methods on [vectors] and [strings], implementations of most +comparison and math operators, and pervasive types like [`Option`] +and [`Result`] live in core. +All Rust programs link to the core library and import its contents, +as if the following were written at the top of the crate. -It is also possible to import just the name of a module (`use -std::list;`, then use `list::find`), to import all identifiers exported -by a given module (`use io::*`), or to import a specific set -of identifiers (`use math::{min, max, pi}`). +~~~ {.xfail-test} +extern mod core; +use core::*; +~~~ -Rust uses different namespaces for modules, types, and values. You -can also rename an identifier when importing using the `=` operator: - -~~~~ -use prnt = io::println; -~~~~ - -## Exporting - -By default, a module exports everything that it defines. This can be -restricted with `export` directives at the top of the module or file. - -~~~~ -mod enc { - export encrypt, decrypt; - const SUPER_SECRET_NUMBER: int = 10; - fn encrypt(n: int) -> int { n + SUPER_SECRET_NUMBER } - fn decrypt(n: int) -> int { n - SUPER_SECRET_NUMBER } -} -~~~~ - -This defines a rock-solid encryption algorithm. Code outside of the -module can refer to the `enc::encrypt` and `enc::decrypt` identifiers -just fine, but it does not have access to `enc::super_secret_number`. - -## Resolution - -The resolution process in Rust simply goes up the chain of contexts, -looking for the name in each context. Nested functions and modules -create new contexts inside their parent function or module. A file -that's part of a bigger crate will have that crate's context as its -parent context. - -Identifiers can shadow each other. In this program, `x` is of type -`int`: - -~~~~ -type MyType = ~str; -fn main() { - type MyType = int; - let x: MyType = 17; -} -~~~~ - -An `use` directive will only import into the namespaces for which -identifiers are actually found. Consider this example: - -~~~~ -mod foo { - fn bar() {} -} - -fn main() { - let bar = 10; - - { - use foo::bar; - let quux = bar; - assert quux == 10; - } -} -~~~~ - -When resolving the type name `bar` in the `quux` definition, the -resolver will first look at local block context for `baz`. This has an -import named `bar`, but that's function, not a value, So it continues -to the `baz` function context and finds a value named `bar` defined -there. - -Normally, multiple definitions of the same identifier in a scope are -disallowed. Local variables defined with `let` are an exception to -this—multiple `let` directives can redefine the same variable in a -single scope. When resolving the name of such a variable, the most -recent definition is used. - -~~~~ -fn main() { - let x = 10; - let x = x + 10; - assert x == 20; -} -~~~~ - -This makes it possible to rebind a variable without actually mutating -it, which is mostly useful for destructuring (which can rebind, but -not assign). +[core]: core/index.html +[vectors]: core/vec.html +[strings]: core/str.html +[`Option`]: core/option.html +[`Result`]: core/result.html # What next? From 0b2ffa5692ce83bbf499262e6023c8f7673f0522 Mon Sep 17 00:00:00 2001 From: Jacob Harris Cryer Kragh Date: Sat, 6 Oct 2012 11:56:29 +0300 Subject: [PATCH 005/292] tutorial: Add missing struct name --- doc/tutorial.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index f73ddd1b4c46..0badbb8c05da 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -879,10 +879,10 @@ parentheses. # enum Direction { North, East, South, West } fn point_from_direction(dir: Direction) -> Point { match dir { - North => {x: 0f, y: 1f}, - East => {x: 1f, y: 0f}, - South => {x: 0f, y: -1f}, - West => {x: -1f, y: 0f} + North => Point {x: 0f, y: 1f}, + East => Point {x: 1f, y: 0f}, + South => Point {x: 0f, y: -1f}, + West => Point {x: -1f, y: 0f} } } ~~~~ From ba26dc50cecb66e10e183dc834fb570979a475b7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 22:35:08 -0700 Subject: [PATCH 006/292] docs: Remove more uses of records --- doc/tutorial.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 0badbb8c05da..78a7b5e5f257 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -859,12 +859,12 @@ get at their contents. All variant constructors can be used as patterns, as in this definition of `area`: ~~~~ -# type Point = {x: float, y: float}; +# struct Point {x: float, y: float} # enum Shape { Circle(Point, float), Rectangle(Point, Point) } fn area(sh: Shape) -> float { match sh { Circle(_, size) => float::consts::pi * size * size, - Rectangle({x, y}, {x: x2, y: y2}) => (x2 - x) * (y2 - y) + Rectangle(Point {x, y}, Point {x: x2, y: y2}) => (x2 - x) * (y2 - y) } } ~~~~ @@ -875,7 +875,7 @@ their introductory form, nullary enum patterns are written without parentheses. ~~~~ -# type Point = {x: float, y: float}; +# struct Point {x: float, y: float} # enum Direction { North, East, South, West } fn point_from_direction(dir: Direction) -> Point { match dir { From 89f30614c6460490d812c13f871d83ff08883e4a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 22:35:47 -0700 Subject: [PATCH 007/292] Add Jacob Harris Cryer Kragh to AUTHORS.txt --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 4a0bd86b5441..08a3ec77807c 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -49,6 +49,7 @@ Grahame Bowland Haitao Li Ian D. Bollinger Ivano Coppola +Jacob Harris Cryer Kragh Jacob Parker Jason Orendorff Jed Davis From fe5526f49c824b73b00dd8f43bf9b6f97aa2a9a0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 22:40:12 -0700 Subject: [PATCH 008/292] docs: Fix capitalization of section title --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 78a7b5e5f257..1dac6468fdc1 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -179,7 +179,7 @@ mode for your favorite editor, let us know so that we can link to it. [sublime]: http://github.com/dbp/sublime-rust [sublime-pkg]: http://wbond.net/sublime_packages/package_control -# Syntax Basics +# Syntax basics Assuming you've programmed in any C-family language (C++, Java, JavaScript, C#, or PHP), Rust will feel familiar. Code is arranged From b6443519c8b325bd554e8ea7283b02ebe1632e8f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 22:45:48 -0700 Subject: [PATCH 009/292] Remove some redundant info from tutorial --- doc/tutorial.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 1dac6468fdc1..e64de6134d76 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -686,19 +686,7 @@ For more involved iteration, such as going over the elements of a collection, Rust uses higher-order functions. We'll come back to those in a moment. -# Basic datatypes - -The core datatypes of Rust are structs, enums (tagged unions, algebraic data -types), and tuples. They are immutable by default. - -~~~~ -struct Point { x: float, y: float } - -enum Shape { - Circle(Point, float), - Rectangle(Point, Point) -} -~~~~ +# Data structures ## Structs From c6330036a4e20a60f7ade12ed9f4d53b8fc9d762 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 22:47:26 -0700 Subject: [PATCH 010/292] 'The' Rust Language Tutorial --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index e64de6134d76..33b66d0a1cd8 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1,4 +1,4 @@ -% Rust Language Tutorial +% The Rust Language Tutorial # Introduction From f0c4140dd09555e274e472a0d14fd22bbef579d8 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 6 Oct 2012 22:57:40 -0700 Subject: [PATCH 011/292] More tutorial tweaking --- doc/tutorial.md | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 33b66d0a1cd8..c06c9b547727 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -128,19 +128,7 @@ fn main() { If the Rust compiler was installed successfully, running `rustc hello.rs` will produce an executable called `hello` (or `hello.exe` on -Windows) which, upon running, will likely do exactly what you expect -(unless you are on Windows, in which case what it does is subject -to local weather conditions). - -> ***Note:*** That may or may not be hyperbole, but there are some -> 'gotchas' to be aware of on Windows. First, the MinGW environment -> must be set up perfectly. Please read [the -> wiki][wiki-started]. Second, `rustc` may need to be [referred to as -> `rustc.exe`][bug-3319]. It's a bummer, I know, and I am so very -> sorry. - -[bug-3319]: https://github.com/mozilla/rust/issues/3319 -[wiki-started]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust +Windows) which, upon running, will likely do exactly what you expect. The Rust compiler tries to provide useful information when it runs into an error. If you modify the program to make it invalid (for @@ -160,6 +148,15 @@ declaration to appear at the top level of the file—all statements must live inside a function. Rust programs can also be compiled as libraries, and included in other programs. +> ***Note:*** There are some 'gotchas' to be aware of on +> Windows. First, the MinGW environment must be set up +> perfectly. Please read [the wiki][wiki-started]. Second, `rustc` may +> need to be [referred to as `rustc.exe`][bug-3319]. It's a bummer, I +> know. + +[bug-3319]: https://github.com/mozilla/rust/issues/3319 +[wiki-started]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust + ## Editing Rust code There are vim highlighting and indentation scripts in the Rust source From 07fb35227b08d35213a7a17cded9a3933fd09479 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 7 Oct 2012 01:06:07 -0700 Subject: [PATCH 012/292] Tutorial --- doc/tutorial.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index c06c9b547727..dc7dec766efd 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1335,13 +1335,12 @@ stored on the stack, the local heap, or the exchange heap. Borrowed pointers to vectors are also called 'slices'. ~~~ -enum Crayon { - Almond, AntiqueBrass, Apricot, - Aquamarine, Asparagus, AtomicTangerine, - BananaMania, Beaver, Bittersweet, - Black, BlizzardBlue, Blue -} - +# enum Crayon { +# Almond, AntiqueBrass, Apricot, +# Aquamarine, Asparagus, AtomicTangerine, +# BananaMania, Beaver, Bittersweet, +# Black, BlizzardBlue, Blue +# } // A fixed-size stack vector let stack_crayons: [Crayon * 3] = [Almond, AntiqueBrass, Apricot]; @@ -1368,8 +1367,7 @@ let your_crayons = ~[BananaMania, Beaver, Bittersweet]; // Add two vectors to create a new one let our_crayons = my_crayons + your_crayons; -// += will append to a vector, provided it leves -// in a mutable slot +// += will append to a vector, provided it lives in a mutable slot let mut my_crayons = move my_crayons; my_crayons += your_crayons; ~~~~ From 2a41abb9efee7e07b3989f3a60b994a05c386851 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 7 Oct 2012 01:52:06 -0700 Subject: [PATCH 013/292] Work on the tutorial section on 'do' --- doc/tutorial.md | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index dc7dec766efd..36b118a21a37 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1618,10 +1618,8 @@ call_twice(bare_function); ## Do syntax -The `do` expression is syntactic sugar for use with functions which -take a closure as a final argument, because closures in Rust -are so frequently used in combination with higher-order -functions. +The `do` expression provides a way to treat higher-order functions +(functions that take closures as arguments) as control structures. Consider this function which iterates over a vector of integers, passing in a pointer to each integer in the vector: @@ -1636,20 +1634,22 @@ fn each(v: &[int], op: fn(v: &int)) { } ~~~~ -The reason we pass in a *pointer* to an integer rather than the -integer itself is that this is how the actual `each()` function for -vectors works. Using a pointer means that the function can be used -for vectors of any type, even large structs that would be impractical -to copy out of the vector on each iteration. As a caller, if we use a -closure to provide the final operator argument, we can write it in a -way that has a pleasant, block-like structure. +As an aside, the reason we pass in a *pointer* to an integer rather +than the integer itself is that this is how the actual `each()` +function for vectors works. `vec::each` though is a +[generic](#generics) function, so must be efficient to use for all +types. Passing the elements by pointer avoids copying potentially +large objects. + +As a caller, if we use a closure to provide the final operator +argument, we can write it in a way that has a pleasant, block-like +structure. ~~~~ # fn each(v: &[int], op: fn(v: &int)) { } -# fn do_some_work(i: int) { } +# fn do_some_work(i: &int) { } each(&[1, 2, 3], |n| { - debug!("%i", *n); - do_some_work(*n); + do_some_work(n); }); ~~~~ @@ -1658,10 +1658,9 @@ call that can be written more like a built-in control structure: ~~~~ # fn each(v: &[int], op: fn(v: &int)) { } -# fn do_some_work(i: int) { } +# fn do_some_work(i: &int) { } do each(&[1, 2, 3]) |n| { - debug!("%i", *n); - do_some_work(*n); + do_some_work(n); } ~~~~ @@ -1670,7 +1669,9 @@ final closure inside the argument list it is moved outside of the parenthesis where it looks visually more like a typical block of code. -`do` is often used for task spawning. +`do` is often used to create tasks with the `task::spawn` function. +`spawn` has the signature `spawn(fn: fn~())`. In other words, it +is a function that takes an owned closure that takes no arguments. ~~~~ use task::spawn; @@ -1680,9 +1681,9 @@ do spawn() || { } ~~~~ -That's nice, but look at all those bars and parentheses - that's two empty -argument lists back to back. Wouldn't it be great if they weren't -there? +Look at all those bars and parentheses - that's two empty argument +lists back to back. Since that is so unsightly, empty argument lists +may be omitted from `do` expressions. ~~~~ # use task::spawn; @@ -1691,8 +1692,6 @@ do spawn { } ~~~~ -Empty argument lists can be omitted from `do` expressions. - ## For loops Most iteration in Rust is done with `for` loops. Like `do`, From e1c517ca4815273285ac5699a88ccf0bcdb6103e Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sun, 7 Oct 2012 10:31:34 -0700 Subject: [PATCH 014/292] migrate libsyntax/rustc to auto_serialize2 --- src/libsyntax/ast.rs | 355 ++++++++++++++++++++-------------- src/libsyntax/ast_util.rs | 3 +- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/parse/token.rs | 19 +- src/rustc/metadata/csearch.rs | 4 +- src/rustc/metadata/decoder.rs | 244 +++++++++++------------ src/rustc/metadata/encoder.rs | 91 +++++---- src/rustc/middle/astencode.rs | 172 ++++++++-------- src/rustc/middle/freevars.rs | 6 +- src/rustc/middle/ty.rs | 34 ++-- src/rustc/middle/typeck.rs | 12 +- 12 files changed, 502 insertions(+), 442 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a50189cf5989..1c279f81cc39 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1,33 +1,25 @@ // The Rust abstract syntax tree. +use std::serialization2::{Serializable, + Deserializable, + Serializer, + Deserializer}; use codemap::{span, filename}; -use std::serialization::{Serializer, - Deserializer, - serialize_Option, - deserialize_Option, - serialize_uint, - deserialize_uint, - serialize_int, - deserialize_int, - serialize_i64, - deserialize_i64, - serialize_u64, - deserialize_u64, - serialize_str, - deserialize_str, - serialize_bool, - deserialize_bool}; use parse::token; -/* Note #1972 -- spans are serialized but not deserialized */ -fn serialize_span(_s: S, _v: span) { +impl span: Serializable { + /* Note #1972 -- spans are serialized but not deserialized */ + fn serialize(&self, _s: &S) { } } -fn deserialize_span(_d: D) -> span { - ast_util::dummy_sp() +impl span: Deserializable { + static fn deserialize(_d: &D) -> span { + ast_util::dummy_sp() + } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type spanned = {node: T, span: span}; @@ -42,25 +34,30 @@ macro_rules! interner_key ( // implemented. struct ident { repr: uint } -fn serialize_ident(s: S, i: ident) { - let intr = match unsafe{ - task::local_data::local_data_get(interner_key!()) - } { - None => fail ~"serialization: TLS interner not set up", - Some(intr) => intr - }; +impl ident: Serializable { + fn serialize(&self, s: &S) { + let intr = match unsafe { + task::local_data::local_data_get(interner_key!()) + } { + None => fail ~"serialization: TLS interner not set up", + Some(intr) => intr + }; - s.emit_str(*(*intr).get(i)); + s.emit_owned_str(*(*intr).get(*self)); + } } -fn deserialize_ident(d: D) -> ident { - let intr = match unsafe{ - task::local_data::local_data_get(interner_key!()) - } { - None => fail ~"deserialization: TLS interner not set up", - Some(intr) => intr - }; - (*intr).intern(@d.read_str()) +impl ident: Deserializable { + static fn deserialize(d: &D) -> ident { + let intr = match unsafe { + task::local_data::local_data_get(interner_key!()) + } { + None => fail ~"deserialization: TLS interner not set up", + Some(intr) => intr + }; + + (*intr).intern(@d.read_owned_str()) + } } impl ident: cmp::Eq { @@ -75,23 +72,22 @@ impl ident: to_bytes::IterBytes { } // Functions may or may not have names. -#[auto_serialize] type fn_ident = Option; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type path = {span: span, global: bool, idents: ~[ident], rp: Option<@region>, types: ~[@ty]}; -#[auto_serialize] type crate_num = int; -#[auto_serialize] type node_id = int; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type def_id = {crate: crate_num, node: node_id}; impl def_id : cmp::Eq { @@ -104,7 +100,8 @@ impl def_id : cmp::Eq { const local_crate: crate_num = 0; const crate_node_id: node_id = 0; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum ty_param_bound { bound_copy, bound_send, @@ -113,10 +110,12 @@ enum ty_param_bound { bound_trait(@ty), } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum def { def_fn(def_id, purity), def_static_method(def_id, purity), @@ -293,33 +292,36 @@ enum crate_directive_ { type crate_directive = spanned; -#[auto_serialize] type meta_item = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum meta_item_ { meta_word(~str), meta_list(~str, ~[@meta_item]), meta_name_value(~str, lit), } -#[auto_serialize] type blk = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type blk_ = {view_items: ~[@view_item], stmts: ~[@stmt], expr: Option<@expr>, id: node_id, rules: blk_check_mode}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type pat = {id: node_id, node: pat_, span: span}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type field_pat = {ident: ident, pat: @pat}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum binding_mode { bind_by_value, bind_by_move, @@ -375,7 +377,8 @@ impl binding_mode : cmp::Eq { pure fn ne(other: &binding_mode) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -398,7 +401,8 @@ enum pat_ { pat_range(@expr, @expr), } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum mutability { m_mutbl, m_imm, m_const, } impl mutability : to_bytes::IterBytes { @@ -414,7 +418,8 @@ impl mutability : cmp::Eq { pure fn ne(other: &mutability) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum proto { proto_bare, // foreign fn proto_uniq, // fn~ @@ -429,7 +434,8 @@ impl proto : cmp::Eq { pure fn ne(other: &proto) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -438,7 +444,8 @@ enum vstore { vstore_slice(@region) // &[1,2,3,4](foo)? } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum expr_vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) expr_vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -454,7 +461,8 @@ pure fn is_blockish(p: ast::proto) -> bool { } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum binop { add, subtract, @@ -483,7 +491,8 @@ impl binop : cmp::Eq { pure fn ne(other: &binop) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum unop { box(mutability), uniq(mutability), @@ -534,7 +543,8 @@ impl unop : cmp::Eq { // Generally, after typeck you can get the inferred value // using ty::resolved_T(...). -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum inferable { expl(T), infer(node_id) @@ -573,7 +583,8 @@ impl inferable : cmp::Eq { } // "resolved" mode: the real modes. -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum rmode { by_ref, by_val, by_move, by_copy } impl rmode : to_bytes::IterBytes { @@ -591,13 +602,12 @@ impl rmode : cmp::Eq { } // inferable mode. -#[auto_serialize] type mode = inferable; -#[auto_serialize] type stmt = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum stmt_ { stmt_decl(@decl, node_id), @@ -608,7 +618,8 @@ enum stmt_ { stmt_semi(@expr, node_id), } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum init_op { init_assign, init_move, } impl init_op : cmp::Eq { @@ -631,34 +642,37 @@ impl init_op : cmp::Eq { pure fn ne(other: &init_op) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type initializer = {op: init_op, expr: @expr}; // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type local_ = {is_mutbl: bool, ty: @ty, pat: @pat, init: Option, id: node_id}; -#[auto_serialize] type local = spanned; -#[auto_serialize] type decl = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum decl_ { decl_local(~[@local]), decl_item(@item), } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type field_ = {mutbl: mutability, ident: ident, expr: @expr}; -#[auto_serialize] type field = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum blk_check_mode { default_blk, unsafe_blk, } impl blk_check_mode : cmp::Eq { @@ -673,18 +687,22 @@ impl blk_check_mode : cmp::Eq { pure fn ne(other: &blk_check_mode) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type expr = {id: node_id, callee_id: node_id, node: expr_, span: span}; // Extra node ID is only used for index, assign_op, unary, binary -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum log_level { error, debug, other } // 0 = error, 1 = debug, 2 = other -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum alt_mode { alt_check, alt_exhaustive, } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum expr_ { expr_vstore(@expr, expr_vstore), expr_vec(~[@expr], mutability), @@ -740,15 +758,17 @@ enum expr_ { expr_repeat(@expr /* element */, @expr /* count */, mutability) } -#[auto_serialize] -type capture_item = @{ +#[auto_serialize2] +#[auto_deserialize2] +type capture_item_ = { id: int, is_move: bool, name: ident, // Currently, can only capture a local var. span: span }; -#[auto_serialize] +type capture_item = @capture_item_; + type capture_clause = @~[capture_item]; // @@ -767,7 +787,8 @@ type capture_clause = @~[capture_item]; // else knows what to do with them, so you'll probably get a syntax // error. // -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] #[doc="For macro invocations; parsing is delegated to the macro"] enum token_tree { tt_tok(span, token::token), @@ -829,10 +850,10 @@ enum token_tree { // If you understand that, you have closed to loop and understand the whole // macro system. Congratulations. // -#[auto_serialize] type matcher = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum matcher_ { // match one token match_tok(token::token), @@ -843,19 +864,18 @@ enum matcher_ { match_nonterminal(ident, ident, uint) } -#[auto_serialize] type mac = spanned; -#[auto_serialize] type mac_arg = Option<@expr>; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type mac_body_ = {span: span}; -#[auto_serialize] type mac_body = Option; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum mac_ { mac_invoc(@path, mac_arg, mac_body), // old macro-invocation mac_invoc_tt(@path,~[token_tree]), // new macro-invocation @@ -866,10 +886,10 @@ enum mac_ { mac_var(uint) } -#[auto_serialize] type lit = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum lit_ { lit_str(@~str), lit_int(i64, int_ty), @@ -910,21 +930,24 @@ impl ast::lit_: cmp::Eq { // NB: If you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type mt = {ty: @ty, mutbl: mutability}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_field_ = {ident: ident, mt: mt}; -#[auto_serialize] type ty_field = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_method = {ident: ident, attrs: ~[attribute], purity: purity, decl: fn_decl, tps: ~[ty_param], self_ty: self_ty, id: node_id, span: span}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] // A trait method is either required (meaning it doesn't have an // implementation, just a signature) or provided (meaning it has a default // implementation). @@ -933,7 +956,8 @@ enum trait_method { provided(@method), } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } impl int_ty : to_bytes::IterBytes { @@ -962,7 +986,8 @@ impl int_ty : cmp::Eq { pure fn ne(other: &int_ty) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } impl uint_ty : to_bytes::IterBytes { @@ -989,7 +1014,8 @@ impl uint_ty : cmp::Eq { pure fn ne(other: &uint_ty) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum float_ty { ty_f, ty_f32, ty_f64, } impl float_ty : to_bytes::IterBytes { @@ -1007,11 +1033,13 @@ impl float_ty : cmp::Eq { pure fn ne(other: &float_ty) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type ty = {id: node_id, node: ty_, span: span}; // Not represented directly in the AST, referred to by name through a ty_path. -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum prim_ty { ty_int(int_ty), ty_uint(uint_ty), @@ -1058,10 +1086,12 @@ impl prim_ty : cmp::Eq { pure fn ne(other: &prim_ty) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type region = {id: node_id, node: region_}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum region_ { re_anon, re_static, @@ -1069,7 +1099,8 @@ enum region_ { re_named(ident) } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -1108,16 +1139,19 @@ impl ty : to_bytes::IterBytes { } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type fn_decl = {inputs: ~[arg], output: @ty, cf: ret_style}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum purity { pure_fn, // declared with "pure fn" unsafe_fn, // declared with "unsafe fn" @@ -1138,7 +1172,8 @@ impl purity : cmp::Eq { pure fn ne(other: &purity) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum ret_style { noreturn, // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) @@ -1163,7 +1198,8 @@ impl ret_style : cmp::Eq { pure fn ne(other: &ret_style) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum self_ty_ { sty_static, // no self: static method sty_by_ref, // old by-reference self: `` @@ -1217,20 +1253,22 @@ impl self_ty_ : cmp::Eq { pure fn ne(other: &self_ty_) -> bool { !self.eq(other) } } -#[auto_serialize] type self_ty = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type method = {ident: ident, attrs: ~[attribute], tps: ~[ty_param], self_ty: self_ty, purity: purity, decl: fn_decl, body: blk, id: node_id, span: span, self_id: node_id, vis: visibility}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type _mod = {view_items: ~[@view_item], items: ~[@item]}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_abi { foreign_abi_rust_intrinsic, foreign_abi_cdecl, @@ -1238,7 +1276,8 @@ enum foreign_abi { } // Foreign mods can be named or anonymous -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_mod_sort { named, anonymous } impl foreign_mod_sort : cmp::Eq { @@ -1262,39 +1301,48 @@ impl foreign_abi : cmp::Eq { pure fn ne(other: &foreign_abi) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type foreign_mod = {sort: foreign_mod_sort, view_items: ~[@view_item], items: ~[@foreign_item]}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type variant_arg = {ty: @ty, id: node_id}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum variant_kind { tuple_variant_kind(~[variant_arg]), struct_variant_kind(@struct_def), enum_variant_kind(enum_def) } -#[auto_serialize] -enum enum_def = { variants: ~[variant], common: Option<@struct_def> }; +#[auto_serialize2] +#[auto_deserialize2] +type enum_def_ = { variants: ~[variant], common: Option<@struct_def> }; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] +enum enum_def = enum_def_; + +#[auto_serialize2] +#[auto_deserialize2] type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, id: node_id, disr_expr: Option<@expr>, vis: visibility}; -#[auto_serialize] type variant = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type path_list_ident_ = {name: ident, id: node_id}; -#[auto_serialize] type path_list_ident = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum namespace { module_ns, type_value_ns } impl namespace : cmp::Eq { @@ -1304,10 +1352,10 @@ impl namespace : cmp::Eq { pure fn ne(other: &namespace) -> bool { !self.eq(other) } } -#[auto_serialize] type view_path = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum view_path_ { // quux = foo::bar::baz @@ -1324,11 +1372,13 @@ enum view_path_ { view_path_list(@path, ~[path_list_ident], node_id) } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type view_item = {node: view_item_, attrs: ~[attribute], vis: visibility, span: span}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum view_item_ { view_item_use(ident, ~[@meta_item], node_id), view_item_import(~[@view_path]), @@ -1336,13 +1386,13 @@ enum view_item_ { } // Meta-data associated with an item -#[auto_serialize] type attribute = spanned; // Distinguishes between attributes that decorate items and attributes that // are contained as statements within items. These two cases need to be // distinguished for pretty-printing. -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum attr_style { attr_outer, attr_inner, } impl attr_style : cmp::Eq { @@ -1353,7 +1403,8 @@ impl attr_style : cmp::Eq { } // doc-comments are promoted to attributes that have is_sugared_doc = true -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; /* @@ -1365,10 +1416,12 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; conceptually, the impl_id stands in for the pair of (this class, this trait) */ -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum visibility { public, private, inherited } impl visibility : cmp::Eq { @@ -1385,23 +1438,25 @@ impl visibility : cmp::Eq { pure fn ne(other: &visibility) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type struct_field_ = { kind: struct_field_kind, id: node_id, ty: @ty }; -#[auto_serialize] type struct_field = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum struct_field_kind { named_field(ident, class_mutability, visibility), unnamed_field // element of a tuple-like struct } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type struct_def = { traits: ~[@trait_ref], /* traits this struct implements */ fields: ~[@struct_field], /* fields */ @@ -1417,12 +1472,14 @@ type struct_def = { FIXME (#3300): Should allow items to be anonymous. Right now we just use dummy names for anon items. */ -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type item = {ident: ident, attrs: ~[attribute], id: node_id, node: item_, vis: visibility, span: span}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum item_ { item_const(@ty, @expr), item_fn(fn_decl, purity, ~[ty_param], blk), @@ -1439,7 +1496,8 @@ enum item_ { item_mac(mac), } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum class_mutability { class_mutable, class_immutable } impl class_mutability : to_bytes::IterBytes { @@ -1460,26 +1518,27 @@ impl class_mutability : cmp::Eq { pure fn ne(other: &class_mutability) -> bool { !self.eq(other) } } -#[auto_serialize] type class_ctor = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type class_ctor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, dec: fn_decl, body: blk}; -#[auto_serialize] type class_dtor = spanned; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type class_dtor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, body: blk}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type foreign_item = {ident: ident, attrs: ~[attribute], @@ -1488,7 +1547,8 @@ type foreign_item = span: span, vis: visibility}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_item_ { foreign_item_fn(fn_decl, purity, ~[ty_param]), foreign_item_const(@ty) @@ -1497,7 +1557,8 @@ enum foreign_item_ { // The data we save and restore about an inlined item or method. This is not // part of the AST that we parse from a file, but it becomes part of the tree // that we trans. -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index e8099de246cc..47cbdb7ac6cb 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -406,7 +406,8 @@ fn dtor_dec() -> fn_decl { // ______________________________________________________________________ // Enumerating the IDs which appear in an AST -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type id_range = {min: node_id, max: node_id}; fn empty(range: id_range) -> bool { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 9a31cc1d8f67..53880baea9b8 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -54,7 +54,7 @@ enum syntax_extension { // macro_defining() is obsolete, remove when #old_macros go away. macro_defining(macro_definer), - // #[auto_serialize] and such. will probably survive death of #old_macros + // #[auto_serialize2] and such. will probably survive death of #old_macros item_decorator(item_decorator), // Token-tree expanders diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 22e2cfcde6b5..2d0b2f4c80ab 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -124,7 +124,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, } // This is a secondary mechanism for invoking syntax extensions on items: -// "decorator" attributes, such as #[auto_serialize]. These are invoked by an +// "decorator" attributes, such as #[auto_serialize2]. These are invoked by an // attribute prefixing an item, and are interpreted by feeding the item // through the named attribute _as a syntax extension_ and splicing in the // resulting item vec into place in favour of the decorator. Note that diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 99b789cf63fc..19e79a4ae7a9 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -1,18 +1,9 @@ use util::interner; use util::interner::interner; use std::map::HashMap; -use std::serialization::{Serializer, - Deserializer, - serialize_uint, - deserialize_uint, - serialize_i64, - deserialize_i64, - serialize_u64, - deserialize_u64, - serialize_bool, - deserialize_bool}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum binop { PLUS, MINUS, @@ -26,7 +17,8 @@ enum binop { SHR, } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum token { /* Expression-operator symbols. */ EQ, @@ -83,7 +75,8 @@ enum token { EOF, } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] /// For interpolation during macro expansion. enum nonterminal { nt_item(@ast::item), diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index e29a4fd436bc..52813eb6b75d 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -1,6 +1,6 @@ // Searching for information from the cstore -use std::{ebml}; +use std::ebml2; use syntax::ast; use syntax::ast_util; use syntax::ast_map; @@ -136,7 +136,7 @@ fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id, def: ast::def_id) -> ty::ty_param_bounds_and_ty { let cstore = tcx.cstore; let cdata = cstore::get_crate_data(cstore, class_id.crate); - let all_items = ebml::get_doc(ebml::Doc(cdata.data), tag_items); + let all_items = ebml2::get_doc(ebml2::Doc(cdata.data), tag_items); debug!("Looking up %?", class_id); let class_doc = expect(tcx.diag, decoder::maybe_find_item(class_id.node, all_items), diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 0e6bc2aee15a..197e567ab2f8 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -1,7 +1,8 @@ // Decoding metadata from a single crate's metadata -use std::{ebml, map}; +use std::{ebml2, map}; use std::map::HashMap; +use std::serialization2::deserialize; use io::WriterUtil; use dvec::DVec; use syntax::{ast, ast_util}; @@ -63,25 +64,25 @@ export translate_def_id; // what crate that's in and give us a def_id that makes sense for the current // build. -fn lookup_hash(d: ebml::Doc, eq_fn: fn(x:&[u8]) -> bool, hash: uint) -> - Option { - let index = ebml::get_doc(d, tag_index); - let table = ebml::get_doc(index, tag_index_table); +fn lookup_hash(d: ebml2::Doc, eq_fn: fn(x:&[u8]) -> bool, hash: uint) -> + Option { + let index = ebml2::get_doc(d, tag_index); + let table = ebml2::get_doc(index, tag_index_table); let hash_pos = table.start + hash % 256u * 4u; let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4u) as uint; - let {tag:_, doc:bucket} = ebml::doc_at(d.data, pos); + let tagged_doc = ebml2::doc_at(d.data, pos); let belt = tag_index_buckets_bucket_elt; - for ebml::tagged_docs(bucket, belt) |elt| { + for ebml2::tagged_docs(tagged_doc.doc, belt) |elt| { let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4u) as uint; if eq_fn(vec::view(*elt.data, elt.start + 4u, elt.end)) { - return Some(ebml::doc_at(d.data, pos).doc); + return Some(ebml2::doc_at(d.data, pos).doc); } }; None } -fn maybe_find_item(item_id: int, items: ebml::Doc) -> Option { +fn maybe_find_item(item_id: int, items: ebml2::Doc) -> Option { fn eq_item(bytes: &[u8], item_id: int) -> bool { return io::u64_from_be_bytes(vec::view(bytes, 0u, 4u), 0u, 4u) as int == item_id; @@ -91,14 +92,14 @@ fn maybe_find_item(item_id: int, items: ebml::Doc) -> Option { item_id.hash() as uint) } -fn find_item(item_id: int, items: ebml::Doc) -> ebml::Doc { +fn find_item(item_id: int, items: ebml2::Doc) -> ebml2::Doc { return maybe_find_item(item_id, items).get(); } -// Looks up an item in the given metadata and returns an ebml doc pointing +// Looks up an item in the given metadata and returns an ebml2 doc pointing // to the item data. -fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc { - let items = ebml::get_doc(ebml::Doc(data), tag_items); +fn lookup_item(item_id: int, data: @~[u8]) -> ebml2::Doc { + let items = ebml2::get_doc(ebml2::Doc(data), tag_items); match maybe_find_item(item_id, items) { None => fail(fmt!("lookup_item: id not found: %d", item_id)), Some(d) => d @@ -136,9 +137,9 @@ impl Family : cmp::Eq { pure fn ne(other: &Family) -> bool { !self.eq(other) } } -fn item_family(item: ebml::Doc) -> Family { - let fam = ebml::get_doc(item, tag_items_data_item_family); - match ebml::doc_as_u8(fam) as char { +fn item_family(item: ebml2::Doc) -> Family { + let fam = ebml2::get_doc(item, tag_items_data_item_family); + match ebml2::doc_as_u8(fam) as char { 'c' => Const, 'f' => Fn, 'u' => UnsafeFn, @@ -164,59 +165,59 @@ fn item_family(item: ebml::Doc) -> Family { } } -fn item_symbol(item: ebml::Doc) -> ~str { - let sym = ebml::get_doc(item, tag_items_data_item_symbol); - return str::from_bytes(ebml::doc_data(sym)); +fn item_symbol(item: ebml2::Doc) -> ~str { + let sym = ebml2::get_doc(item, tag_items_data_item_symbol); + return str::from_bytes(ebml2::doc_data(sym)); } -fn item_parent_item(d: ebml::Doc) -> Option { - for ebml::tagged_docs(d, tag_items_data_parent_item) |did| { - return Some(ebml::with_doc_data(did, |d| parse_def_id(d))); +fn item_parent_item(d: ebml2::Doc) -> Option { + for ebml2::tagged_docs(d, tag_items_data_parent_item) |did| { + return Some(ebml2::with_doc_data(did, |d| parse_def_id(d))); } None } -fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id { - let tagdoc = ebml::get_doc(d, tag_def_id); - return translate_def_id(cdata, ebml::with_doc_data(tagdoc, +fn item_def_id(d: ebml2::Doc, cdata: cmd) -> ast::def_id { + let tagdoc = ebml2::get_doc(d, tag_def_id); + return translate_def_id(cdata, ebml2::with_doc_data(tagdoc, |d| parse_def_id(d))); } -fn each_reexport(d: ebml::Doc, f: fn(ebml::Doc) -> bool) { - for ebml::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| { +fn each_reexport(d: ebml2::Doc, f: fn(ebml2::Doc) -> bool) { + for ebml2::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| { if !f(reexport_doc) { return; } } } -fn field_mutability(d: ebml::Doc) -> ast::class_mutability { +fn field_mutability(d: ebml2::Doc) -> ast::class_mutability { // Use maybe_get_doc in case it's a method option::map_default( - &ebml::maybe_get_doc(d, tag_class_mut), + &ebml2::maybe_get_doc(d, tag_class_mut), ast::class_immutable, |d| { - match ebml::doc_as_u8(*d) as char { + match ebml2::doc_as_u8(*d) as char { 'm' => ast::class_mutable, _ => ast::class_immutable } }) } -fn variant_disr_val(d: ebml::Doc) -> Option { - do option::chain(ebml::maybe_get_doc(d, tag_disr_val)) |val_doc| { - int::parse_bytes(ebml::doc_data(val_doc), 10u) +fn variant_disr_val(d: ebml2::Doc) -> Option { + do option::chain(ebml2::maybe_get_doc(d, tag_disr_val)) |val_doc| { + int::parse_bytes(ebml2::doc_data(val_doc), 10u) } } -fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { - let tp = ebml::get_doc(doc, tag_items_data_item_type); +fn doc_type(doc: ebml2::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { + let tp = ebml2::get_doc(doc, tag_items_data_item_type); parse_ty_data(tp.data, cdata.cnum, tp.start, tcx, |did| { translate_def_id(cdata, did) }) } -fn item_type(item_id: ast::def_id, item: ebml::Doc, +fn item_type(item_id: ast::def_id, item: ebml2::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { let t = doc_type(item, tcx, cdata); if family_names_type(item_family(item)) { @@ -224,18 +225,18 @@ fn item_type(item_id: ast::def_id, item: ebml::Doc, } else { t } } -fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] { +fn item_impl_traits(item: ebml2::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] { let mut results = ~[]; - for ebml::tagged_docs(item, tag_impl_trait) |ity| { + for ebml2::tagged_docs(item, tag_impl_trait) |ity| { results.push(doc_type(ity, tcx, cdata)); }; results } -fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) +fn item_ty_param_bounds(item: ebml2::Doc, tcx: ty::ctxt, cdata: cmd) -> @~[ty::param_bounds] { let mut bounds = ~[]; - for ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| { + for ebml2::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| { let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx, |did| { translate_def_id(cdata, did) }); @@ -244,43 +245,42 @@ fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) @bounds } -fn item_ty_region_param(item: ebml::Doc) -> Option { - ebml::maybe_get_doc(item, tag_region_param).map(|doc| { - let d = ebml::ebml_deserializer(*doc); - ty::deserialize_region_variance(d) +fn item_ty_region_param(item: ebml2::Doc) -> Option { + ebml2::maybe_get_doc(item, tag_region_param).map(|doc| { + deserialize(&ebml2::Deserializer(*doc)) }) } -fn item_ty_param_count(item: ebml::Doc) -> uint { +fn item_ty_param_count(item: ebml2::Doc) -> uint { let mut n = 0u; - ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds, + ebml2::tagged_docs(item, tag_items_data_item_ty_param_bounds, |_p| { n += 1u; true } ); n } -fn enum_variant_ids(item: ebml::Doc, cdata: cmd) -> ~[ast::def_id] { +fn enum_variant_ids(item: ebml2::Doc, cdata: cmd) -> ~[ast::def_id] { let mut ids: ~[ast::def_id] = ~[]; let v = tag_items_data_item_variant; - for ebml::tagged_docs(item, v) |p| { - let ext = ebml::with_doc_data(p, |d| parse_def_id(d)); + for ebml2::tagged_docs(item, v) |p| { + let ext = ebml2::with_doc_data(p, |d| parse_def_id(d)); ids.push({crate: cdata.cnum, node: ext.node}); }; return ids; } -fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path { - let path_doc = ebml::get_doc(item_doc, tag_path); +fn item_path(intr: @ident_interner, item_doc: ebml2::Doc) -> ast_map::path { + let path_doc = ebml2::get_doc(item_doc, tag_path); - let len_doc = ebml::get_doc(path_doc, tag_path_len); - let len = ebml::doc_as_u32(len_doc) as uint; + let len_doc = ebml2::get_doc(path_doc, tag_path_len); + let len = ebml2::doc_as_u32(len_doc) as uint; let mut result = vec::with_capacity(len); - for ebml::docs(path_doc) |tag, elt_doc| { + for ebml2::docs(path_doc) |tag, elt_doc| { if tag == tag_path_elt_mod { - let str = ebml::doc_as_str(elt_doc); + let str = ebml2::doc_as_str(elt_doc); result.push(ast_map::path_mod(intr.intern(@str))); } else if tag == tag_path_elt_name { - let str = ebml::doc_as_str(elt_doc); + let str = ebml2::doc_as_str(elt_doc); result.push(ast_map::path_name(intr.intern(@str))); } else { // ignore tag_path_len element @@ -290,12 +290,12 @@ fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path { return result; } -fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident { - let name = ebml::get_doc(item, tag_paths_data_name); - intr.intern(@str::from_bytes(ebml::doc_data(name))) +fn item_name(intr: @ident_interner, item: ebml2::Doc) -> ast::ident { + let name = ebml2::get_doc(item, tag_paths_data_name); + intr.intern(@str::from_bytes(ebml2::doc_data(name))) } -fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) +fn item_to_def_like(item: ebml2::Doc, did: ast::def_id, cnum: ast::crate_num) -> def_like { let fam = item_family(item); match fam { @@ -367,10 +367,10 @@ fn get_impl_traits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::t] { fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, name: ast::ident) -> ast::def_id { - let items = ebml::get_doc(ebml::Doc(cdata.data), tag_items); + let items = ebml2::get_doc(ebml2::Doc(cdata.data), tag_items); let mut found = None; - for ebml::tagged_docs(find_item(id, items), tag_item_impl_method) |mid| { - let m_did = ebml::with_doc_data(mid, |d| parse_def_id(d)); + for ebml2::tagged_docs(find_item(id, items), tag_item_impl_method) |mid| { + let m_did = ebml2::with_doc_data(mid, |d| parse_def_id(d)); if item_name(intr, find_item(m_did.node, items)) == name { found = Some(translate_def_id(cdata, m_did)); } @@ -380,14 +380,14 @@ fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, fn get_class_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, name: ast::ident) -> ast::def_id { - let items = ebml::get_doc(ebml::Doc(cdata.data), tag_items); + let items = ebml2::get_doc(ebml2::Doc(cdata.data), tag_items); let mut found = None; let cls_items = match maybe_find_item(id, items) { Some(it) => it, None => fail (fmt!("get_class_method: class id not found \ when looking up method %s", *intr.get(name))) }; - for ebml::tagged_docs(cls_items, tag_item_trait_method) |mid| { + for ebml2::tagged_docs(cls_items, tag_item_trait_method) |mid| { let m_did = item_def_id(mid, cdata); if item_name(intr, mid) == name { found = Some(m_did); @@ -401,16 +401,16 @@ fn get_class_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, } fn class_dtor(cdata: cmd, id: ast::node_id) -> Option { - let items = ebml::get_doc(ebml::Doc(cdata.data), tag_items); + let items = ebml2::get_doc(ebml2::Doc(cdata.data), tag_items); let mut found = None; let cls_items = match maybe_find_item(id, items) { Some(it) => it, None => fail (fmt!("class_dtor: class id not found \ when looking up dtor for %d", id)) }; - for ebml::tagged_docs(cls_items, tag_item_dtor) |doc| { - let doc1 = ebml::get_doc(doc, tag_def_id); - let did = ebml::with_doc_data(doc1, |d| parse_def_id(d)); + for ebml2::tagged_docs(cls_items, tag_item_dtor) |doc| { + let doc1 = ebml2::get_doc(doc, tag_def_id); + let did = ebml2::with_doc_data(doc1, |d| parse_def_id(d)); found = Some(translate_def_id(cdata, did)); }; found @@ -452,14 +452,14 @@ fn path_entry(path_string: ~str, def_like: def_like) -> path_entry { /// Iterates over all the paths in the given crate. fn each_path(intr: @ident_interner, cdata: cmd, f: fn(path_entry) -> bool) { - let root = ebml::Doc(cdata.data); - let items = ebml::get_doc(root, tag_items); - let items_data = ebml::get_doc(items, tag_items_data); + let root = ebml2::Doc(cdata.data); + let items = ebml2::get_doc(root, tag_items); + let items_data = ebml2::get_doc(items, tag_items_data); let mut broken = false; // First, go through all the explicit items. - for ebml::tagged_docs(items_data, tag_items_data_item) |item_doc| { + for ebml2::tagged_docs(items_data, tag_items_data_item) |item_doc| { if !broken { let path = ast_map::path_to_str_with_sep( item_path(intr, item_doc), ~"::", intr); @@ -482,16 +482,16 @@ fn each_path(intr: @ident_interner, cdata: cmd, f: fn(path_entry) -> bool) { for each_reexport(item_doc) |reexport_doc| { if !broken { let def_id_doc = - ebml::get_doc(reexport_doc, + ebml2::get_doc(reexport_doc, tag_items_data_item_reexport_def_id); let def_id = - ebml::with_doc_data(def_id_doc, |d| parse_def_id(d)); + ebml2::with_doc_data(def_id_doc, |d| parse_def_id(d)); let def_id = translate_def_id(cdata, def_id); let reexport_name_doc = - ebml::get_doc(reexport_doc, + ebml2::get_doc(reexport_doc, tag_items_data_item_reexport_name); - let reexport_name = ebml::doc_as_str(reexport_name_doc); + let reexport_name = ebml2::doc_as_str(reexport_name_doc); let reexport_path; if path == ~"" { @@ -540,7 +540,7 @@ type decode_inlined_item = fn( cdata: cstore::crate_metadata, tcx: ty::ctxt, path: ast_map::path, - par_doc: ebml::Doc) -> Option; + par_doc: ebml2::Doc) -> Option; fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt, id: ast::node_id, @@ -571,7 +571,7 @@ fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt, fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::variant_info] { let data = cdata.data; - let items = ebml::get_doc(ebml::Doc(data), tag_items); + let items = ebml2::get_doc(ebml2::Doc(data), tag_items); let item = find_item(id, items); let mut infos: ~[ty::variant_info] = ~[]; let variant_ids = enum_variant_ids(item, cdata); @@ -609,7 +609,7 @@ type method_info = { type _impl = {did: ast::def_id, ident: ast::ident, methods: ~[@method_info]}; -fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ { +fn get_self_ty(item: ebml2::Doc) -> ast::self_ty_ { fn get_mutability(ch: u8) -> ast::mutability { match ch as char { 'i' => { ast::m_imm } @@ -621,8 +621,8 @@ fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ { } } - let self_type_doc = ebml::get_doc(item, tag_item_trait_method_self_ty); - let string = ebml::doc_as_str(self_type_doc); + let self_type_doc = ebml2::get_doc(item, tag_item_trait_method_self_ty); + let string = ebml2::doc_as_str(self_type_doc); let self_ty_kind = string[0]; match self_ty_kind as char { @@ -638,11 +638,11 @@ fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ { } } -fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc, +fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml2::Doc, base_tps: uint) -> ~[@method_info] { let mut rslt = ~[]; - for ebml::tagged_docs(item, tag_item_impl_method) |doc| { - let m_did = ebml::with_doc_data(doc, |d| parse_def_id(d)); + for ebml2::tagged_docs(item, tag_item_impl_method) |doc| { + let m_did = ebml2::with_doc_data(doc, |d| parse_def_id(d)); let mth_item = lookup_item(m_did.node, cdata.data); let self_ty = get_self_ty(mth_item); rslt.push(@{did: translate_def_id(cdata, m_did), @@ -662,8 +662,8 @@ fn get_impls_for_mod(intr: @ident_interner, cdata: cmd, let data = cdata.data; let mod_item = lookup_item(m_id, data); let mut result = ~[]; - for ebml::tagged_docs(mod_item, tag_mod_impl) |doc| { - let did = ebml::with_doc_data(doc, |d| parse_def_id(d)); + for ebml2::tagged_docs(mod_item, tag_mod_impl) |doc| { + let did = ebml2::with_doc_data(doc, |d| parse_def_id(d)); let local_did = translate_def_id(cdata, did); debug!("(get impls for mod) getting did %? for '%?'", local_did, name); @@ -690,7 +690,7 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, let data = cdata.data; let item = lookup_item(id, data); let mut result = ~[]; - for ebml::tagged_docs(item, tag_item_trait_method) |mth| { + for ebml2::tagged_docs(item, tag_item_trait_method) |mth| { let bounds = item_ty_param_bounds(mth, tcx, cdata); let name = item_name(intr, mth); let ty = doc_type(mth, tcx, cdata); @@ -722,7 +722,7 @@ fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd, } let resulting_methods = @DVec(); - for ebml::tagged_docs(item, tag_item_trait_method) |method| { + for ebml2::tagged_docs(item, tag_item_trait_method) |method| { resulting_methods.push( (item_name(intr, method), get_self_ty(method))); } @@ -734,8 +734,8 @@ fn get_item_attrs(cdata: cmd, f: fn(~[@ast::meta_item])) { let item = lookup_item(node_id, cdata.data); - for ebml::tagged_docs(item, tag_attributes) |attributes| { - for ebml::tagged_docs(attributes, tag_attribute) |attribute| { + for ebml2::tagged_docs(item, tag_attributes) |attributes| { + for ebml2::tagged_docs(attributes, tag_attribute) |attribute| { f(get_meta_items(attribute)); } } @@ -747,7 +747,7 @@ fn get_class_members(intr: @ident_interner, cdata: cmd, id: ast::node_id, let data = cdata.data; let item = lookup_item(id, data); let mut result = ~[]; - for ebml::tagged_docs(item, tag_item_field) |an_item| { + for ebml2::tagged_docs(item, tag_item_field) |an_item| { let f = item_family(an_item); if p(f) { let name = item_name(intr, an_item); @@ -787,15 +787,15 @@ fn family_names_type(fam: Family) -> bool { match fam { Type | Mod | Trait => true, _ => false } } -fn read_path(d: ebml::Doc) -> {path: ~str, pos: uint} { - let desc = ebml::doc_data(d); +fn read_path(d: ebml2::Doc) -> {path: ~str, pos: uint} { + let desc = ebml2::doc_data(d); let pos = io::u64_from_be_bytes(desc, 0u, 4u) as uint; let pathbytes = vec::slice::(desc, 4u, vec::len::(desc)); let path = str::from_bytes(pathbytes); return {path: path, pos: pos}; } -fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str { +fn describe_def(items: ebml2::Doc, id: ast::def_id) -> ~str { if id.crate != ast::local_crate { return ~"external"; } let it = match maybe_find_item(id.node, items) { Some(it) => it, @@ -830,36 +830,36 @@ fn item_family_to_str(fam: Family) -> ~str { } } -fn get_meta_items(md: ebml::Doc) -> ~[@ast::meta_item] { +fn get_meta_items(md: ebml2::Doc) -> ~[@ast::meta_item] { let mut items: ~[@ast::meta_item] = ~[]; - for ebml::tagged_docs(md, tag_meta_item_word) |meta_item_doc| { - let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name); - let n = str::from_bytes(ebml::doc_data(nd)); + for ebml2::tagged_docs(md, tag_meta_item_word) |meta_item_doc| { + let nd = ebml2::get_doc(meta_item_doc, tag_meta_item_name); + let n = str::from_bytes(ebml2::doc_data(nd)); items.push(attr::mk_word_item(n)); }; - for ebml::tagged_docs(md, tag_meta_item_name_value) |meta_item_doc| { - let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name); - let vd = ebml::get_doc(meta_item_doc, tag_meta_item_value); - let n = str::from_bytes(ebml::doc_data(nd)); - let v = str::from_bytes(ebml::doc_data(vd)); + for ebml2::tagged_docs(md, tag_meta_item_name_value) |meta_item_doc| { + let nd = ebml2::get_doc(meta_item_doc, tag_meta_item_name); + let vd = ebml2::get_doc(meta_item_doc, tag_meta_item_value); + let n = str::from_bytes(ebml2::doc_data(nd)); + let v = str::from_bytes(ebml2::doc_data(vd)); // FIXME (#623): Should be able to decode meta_name_value variants, // but currently the encoder just drops them items.push(attr::mk_name_value_item_str(n, v)); }; - for ebml::tagged_docs(md, tag_meta_item_list) |meta_item_doc| { - let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name); - let n = str::from_bytes(ebml::doc_data(nd)); + for ebml2::tagged_docs(md, tag_meta_item_list) |meta_item_doc| { + let nd = ebml2::get_doc(meta_item_doc, tag_meta_item_name); + let n = str::from_bytes(ebml2::doc_data(nd)); let subitems = get_meta_items(meta_item_doc); items.push(attr::mk_list_item(n, subitems)); }; return items; } -fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] { +fn get_attributes(md: ebml2::Doc) -> ~[ast::attribute] { let mut attrs: ~[ast::attribute] = ~[]; - match ebml::maybe_get_doc(md, tag_attributes) { + match ebml2::maybe_get_doc(md, tag_attributes) { option::Some(attrs_d) => { - for ebml::tagged_docs(attrs_d, tag_attribute) |attr_doc| { + for ebml2::tagged_docs(attrs_d, tag_attribute) |attr_doc| { let meta_items = get_meta_items(attr_doc); // Currently it's only possible to have a single meta item on // an attribute @@ -877,13 +877,13 @@ fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] { } fn list_meta_items(intr: @ident_interner, - meta_items: ebml::Doc, out: io::Writer) { + meta_items: ebml2::Doc, out: io::Writer) { for get_meta_items(meta_items).each |mi| { out.write_str(fmt!("%s\n", pprust::meta_item_to_str(*mi, intr))); } } -fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: ~str, +fn list_crate_attributes(intr: @ident_interner, md: ebml2::Doc, hash: ~str, out: io::Writer) { out.write_str(fmt!("=Crate Attributes (%s)=\n", hash)); @@ -895,7 +895,7 @@ fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: ~str, } fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] { - return get_attributes(ebml::Doc(data)); + return get_attributes(ebml2::Doc(data)); } type crate_dep = {cnum: ast::crate_num, name: ast::ident, @@ -903,13 +903,13 @@ type crate_dep = {cnum: ast::crate_num, name: ast::ident, fn get_crate_deps(intr: @ident_interner, data: @~[u8]) -> ~[crate_dep] { let mut deps: ~[crate_dep] = ~[]; - let cratedoc = ebml::Doc(data); - let depsdoc = ebml::get_doc(cratedoc, tag_crate_deps); + let cratedoc = ebml2::Doc(data); + let depsdoc = ebml2::get_doc(cratedoc, tag_crate_deps); let mut crate_num = 1; - fn docstr(doc: ebml::Doc, tag_: uint) -> ~str { - str::from_bytes(ebml::doc_data(ebml::get_doc(doc, tag_))) + fn docstr(doc: ebml2::Doc, tag_: uint) -> ~str { + str::from_bytes(ebml2::doc_data(ebml2::get_doc(doc, tag_))) } - for ebml::tagged_docs(depsdoc, tag_crate_dep) |depdoc| { + for ebml2::tagged_docs(depsdoc, tag_crate_dep) |depdoc| { deps.push({cnum: crate_num, name: intr.intern(@docstr(depdoc, tag_crate_dep_name)), vers: docstr(depdoc, tag_crate_dep_vers), @@ -932,9 +932,9 @@ fn list_crate_deps(intr: @ident_interner, data: @~[u8], out: io::Writer) { } fn get_crate_hash(data: @~[u8]) -> ~str { - let cratedoc = ebml::Doc(data); - let hashdoc = ebml::get_doc(cratedoc, tag_crate_hash); - return str::from_bytes(ebml::doc_data(hashdoc)); + let cratedoc = ebml2::Doc(data); + let hashdoc = ebml2::get_doc(cratedoc, tag_crate_hash); + return str::from_bytes(ebml2::doc_data(hashdoc)); } fn get_crate_vers(data: @~[u8]) -> ~str { @@ -988,7 +988,7 @@ fn get_crate_module_paths(intr: @ident_interner, cdata: cmd) fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8], out: io::Writer) { let hash = get_crate_hash(bytes); - let md = ebml::Doc(bytes); + let md = ebml2::Doc(bytes); list_crate_attributes(intr, md, hash, out); list_crate_deps(intr, bytes, out); } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index fe432edeec69..95696a141566 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -2,10 +2,10 @@ use util::ppaux::ty_to_str; -use std::{ebml, map}; +use std::{ebml2, map}; use std::map::HashMap; use io::WriterUtil; -use ebml::Writer; +use ebml2::Serializer; use syntax::ast::*; use syntax::print::pprust; use syntax::{ast_util, visit}; @@ -40,7 +40,7 @@ export encode_def_id; type abbrev_map = map::HashMap; type encode_inlined_item = fn@(ecx: @encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml2::Serializer, path: ast_map::path, ii: ast::inlined_item); @@ -86,25 +86,25 @@ fn reachable(ecx: @encode_ctxt, id: node_id) -> bool { ecx.reachable.contains_key(id) } -fn encode_name(ecx: @encode_ctxt, ebml_w: ebml::Writer, name: ident) { +fn encode_name(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, name: ident) { ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name)); } -fn encode_def_id(ebml_w: ebml::Writer, id: def_id) { +fn encode_def_id(ebml_w: ebml2::Serializer, id: def_id) { ebml_w.wr_tagged_str(tag_def_id, def_to_str(id)); } -fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, it: @ast::item) { let opt_rp = ecx.tcx.region_paramd_items.find(it.id); for opt_rp.each |rp| { do ebml_w.wr_tag(tag_region_param) { - ty::serialize_region_variance(ebml_w, *rp); + (*rp).serialize(&ebml_w); } } } -fn encode_mutability(ebml_w: ebml::Writer, mt: class_mutability) { +fn encode_mutability(ebml_w: ebml2::Serializer, mt: class_mutability) { do ebml_w.wr_tag(tag_class_mut) { let val = match mt { class_immutable => 'a', @@ -116,7 +116,7 @@ fn encode_mutability(ebml_w: ebml::Writer, mt: class_mutability) { type entry = {val: T, pos: uint}; -fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: &[ident], +fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, path: &[ident], index: &mut ~[entry<~str>], name: ident) { let mut full_path = ~[]; full_path.push_all(path); @@ -127,7 +127,8 @@ fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: &[ident], pos: ebml_w.writer.tell()}); } -fn encode_trait_ref(ebml_w: ebml::Writer, ecx: @encode_ctxt, t: @trait_ref) { +fn encode_trait_ref(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, + t: @trait_ref) { ebml_w.start_tag(tag_impl_trait); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, t.ref_id)); ebml_w.end_tag(); @@ -135,7 +136,7 @@ fn encode_trait_ref(ebml_w: ebml::Writer, ecx: @encode_ctxt, t: @trait_ref) { // Item info table encoding -fn encode_family(ebml_w: ebml::Writer, c: char) { +fn encode_family(ebml_w: ebml2::Serializer, c: char) { ebml_w.start_tag(tag_items_data_item_family); ebml_w.writer.write(&[c as u8]); ebml_w.end_tag(); @@ -143,7 +144,7 @@ fn encode_family(ebml_w: ebml::Writer, c: char) { fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) } -fn encode_ty_type_param_bounds(ebml_w: ebml::Writer, ecx: @encode_ctxt, +fn encode_ty_type_param_bounds(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, params: @~[ty::param_bounds]) { let ty_str_ctxt = @{diag: ecx.diag, ds: def_to_str, @@ -157,7 +158,7 @@ fn encode_ty_type_param_bounds(ebml_w: ebml::Writer, ecx: @encode_ctxt, } } -fn encode_type_param_bounds(ebml_w: ebml::Writer, ecx: @encode_ctxt, +fn encode_type_param_bounds(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, params: ~[ty_param]) { let ty_param_bounds = @params.map(|param| ecx.tcx.ty_param_bounds.get(param.id)); @@ -165,13 +166,13 @@ fn encode_type_param_bounds(ebml_w: ebml::Writer, ecx: @encode_ctxt, } -fn encode_variant_id(ebml_w: ebml::Writer, vid: def_id) { +fn encode_variant_id(ebml_w: ebml2::Serializer, vid: def_id) { ebml_w.start_tag(tag_items_data_item_variant); ebml_w.writer.write(str::to_bytes(def_to_str(vid))); ebml_w.end_tag(); } -fn write_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) { +fn write_type(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, typ: ty::t) { let ty_str_ctxt = @{diag: ecx.diag, ds: def_to_str, @@ -181,7 +182,8 @@ fn write_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) { tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ); } -fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Writer, vstore: ty::vstore) { +fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, + vstore: ty::vstore) { let ty_str_ctxt = @{diag: ecx.diag, ds: def_to_str, @@ -191,13 +193,13 @@ fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Writer, vstore: ty::vstore) { tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore); } -fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) { +fn encode_type(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, typ: ty::t) { ebml_w.start_tag(tag_items_data_item_type); write_type(ecx, ebml_w, typ); ebml_w.end_tag(); } -fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml::Writer, id: node_id) { +fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); let sym = match ecx.item_symbols.find(id) { Some(x) => x, @@ -210,25 +212,27 @@ fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml::Writer, id: node_id) { ebml_w.end_tag(); } -fn encode_discriminant(ecx: @encode_ctxt, ebml_w: ebml::Writer, id: node_id) { +fn encode_discriminant(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, + id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); ebml_w.writer.write(str::to_bytes(ecx.discrim_symbols.get(id))); ebml_w.end_tag(); } -fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml::Writer, disr_val: int) { +fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml2::Serializer, + disr_val: int) { ebml_w.start_tag(tag_disr_val); ebml_w.writer.write(str::to_bytes(int::to_str(disr_val,10u))); ebml_w.end_tag(); } -fn encode_parent_item(ebml_w: ebml::Writer, id: def_id) { +fn encode_parent_item(ebml_w: ebml2::Serializer, id: def_id) { ebml_w.start_tag(tag_items_data_parent_item); ebml_w.writer.write(str::to_bytes(def_to_str(id))); ebml_w.end_tag(); } -fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, id: node_id, variants: ~[variant], path: ast_map::path, index: @mut ~[entry], ty_params: ~[ty_param]) { @@ -265,9 +269,9 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::Writer, } } -fn encode_path(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: ast_map::path, - name: ast_map::path_elt) { - fn encode_path_elt(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_path(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, + path: ast_map::path, name: ast_map::path_elt) { + fn encode_path_elt(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, elt: ast_map::path_elt) { let (tag, name) = match elt { ast_map::path_mod(name) => (tag_path_elt_mod, name), @@ -286,7 +290,7 @@ fn encode_path(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: ast_map::path, } } -fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::Writer, md: _mod, +fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, md: _mod, id: node_id, path: ast_map::path, name: ident) { ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(id)); @@ -344,7 +348,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::Writer, md: _mod, ebml_w.end_tag(); } -fn encode_visibility(ebml_w: ebml::Writer, visibility: visibility) { +fn encode_visibility(ebml_w: ebml2::Serializer, visibility: visibility) { encode_family(ebml_w, match visibility { public => 'g', private => 'j', @@ -352,7 +356,7 @@ fn encode_visibility(ebml_w: ebml::Writer, visibility: visibility) { }); } -fn encode_self_type(ebml_w: ebml::Writer, self_type: ast::self_ty_) { +fn encode_self_type(ebml_w: ebml2::Serializer, self_type: ast::self_ty_) { ebml_w.start_tag(tag_item_trait_method_self_ty); // Encode the base self type. @@ -385,7 +389,7 @@ fn encode_self_type(ebml_w: ebml::Writer, self_type: ast::self_ty_) { } /* Returns an index of items in this class */ -fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, id: node_id, path: ast_map::path, class_tps: ~[ty_param], fields: ~[@struct_field], @@ -441,7 +445,7 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Writer, } // This is for encoding info for ctors and dtors -fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, id: node_id, ident: ident, path: ast_map::path, item: Option, tps: ~[ty_param]) { ebml_w.start_tag(tag_items_data_item); @@ -466,7 +470,7 @@ fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml::Writer, ebml_w.end_tag(); } -fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, impl_path: ast_map::path, should_inline: bool, parent_id: node_id, m: @method, all_tps: ~[ty_param]) { @@ -516,8 +520,9 @@ fn should_inline(attrs: ~[attribute]) -> bool { } -fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, - index: @mut ~[entry], path: ast_map::path) { +fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, + item: @item, index: @mut ~[entry], + path: ast_map::path) { let tcx = ecx.tcx; let must_write = @@ -528,7 +533,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, }; if !must_write && !reachable(ecx, item.id) { return; } - fn add_to_index_(item: @item, ebml_w: ebml::Writer, + fn add_to_index_(item: @item, ebml_w: ebml2::Serializer, index: @mut ~[entry]) { index.push({val: item.id, pos: ebml_w.writer.tell()}); } @@ -805,7 +810,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, } } -fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, nitem: @foreign_item, index: @mut ~[entry], path: ast_map::path, abi: foreign_abi) { @@ -838,7 +843,7 @@ fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, ebml_w.end_tag(); } -fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, crate: @crate) -> ~[entry] { let index = @mut ~[]; ebml_w.start_tag(tag_items_data); @@ -893,7 +898,7 @@ fn create_index(index: ~[entry]) -> return buckets_frozen; } -fn encode_index(ebml_w: ebml::Writer, buckets: ~[@~[entry]], +fn encode_index(ebml_w: ebml2::Serializer, buckets: ~[@~[entry]], write_fn: fn(io::Writer, T)) { let writer = ebml_w.writer; ebml_w.start_tag(tag_index); @@ -928,7 +933,7 @@ fn write_int(writer: io::Writer, &&n: int) { writer.write_be_u32(n as u32); } -fn encode_meta_item(ebml_w: ebml::Writer, mi: meta_item) { +fn encode_meta_item(ebml_w: ebml2::Serializer, mi: meta_item) { match mi.node { meta_word(name) => { ebml_w.start_tag(tag_meta_item_word); @@ -965,7 +970,7 @@ fn encode_meta_item(ebml_w: ebml::Writer, mi: meta_item) { } } -fn encode_attributes(ebml_w: ebml::Writer, attrs: ~[attribute]) { +fn encode_attributes(ebml_w: ebml2::Serializer, attrs: ~[attribute]) { ebml_w.start_tag(tag_attributes); for attrs.each |attr| { ebml_w.start_tag(tag_attribute); @@ -1026,7 +1031,7 @@ fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] { return attrs; } -fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, cstore: cstore::cstore) { fn get_ordered_deps(ecx: @encode_ctxt, cstore: cstore::cstore) @@ -1072,7 +1077,7 @@ fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::Writer, ebml_w.end_tag(); } -fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml::Writer, +fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, dep: decoder::crate_dep) { ebml_w.start_tag(tag_crate_dep); ebml_w.start_tag(tag_crate_dep_name); @@ -1087,7 +1092,7 @@ fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml::Writer, ebml_w.end_tag(); } -fn encode_hash(ebml_w: ebml::Writer, hash: ~str) { +fn encode_hash(ebml_w: ebml2::Serializer, hash: ~str) { ebml_w.start_tag(tag_crate_hash); ebml_w.writer.write(str::to_bytes(hash)); ebml_w.end_tag(); @@ -1125,7 +1130,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { type_abbrevs: ty::new_ty_hash() }); - let ebml_w = ebml::Writer(wr as io::Writer); + let ebml_w = ebml2::Serializer(wr as io::Writer); encode_hash(ebml_w, ecx.link_meta.extras_hash); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index a364c1d75d43..39ec58c079ed 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -7,23 +7,21 @@ use syntax::visit; use syntax::ast_map; use syntax::ast_util; use syntax::codemap::span; -use std::ebml; -use std::ebml::Writer; -use std::ebml::get_doc; +use std::ebml2; +use std::ebml2::Serializer; +use std::ebml2::get_doc; use std::map::HashMap; -use std::serialization::Serializer; -use std::serialization::Deserializer; -use std::serialization::SerializerHelpers; -use std::serialization::DeserializerHelpers; -use std::prettyprint::Serializer; +use std::serialization2; +use std::serialization2::{Serializable, + SerializerHelpers, + DeserializerHelpers, + deserialize}; use middle::{ty, typeck}; use middle::typeck::{method_origin, method_map_entry, vtable_res, vtable_origin}; use driver::session::session; -use middle::freevars::{freevar_entry, - serialize_freevar_entry, - deserialize_freevar_entry}; +use middle::freevars::freevar_entry; use c = metadata::common; use e = metadata::encoder; use cstore = metadata::cstore; @@ -76,7 +74,7 @@ trait tr { // Top-level methods. fn encode_inlined_item(ecx: @e::encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml2::Serializer, path: ast_map::path, ii: ast::inlined_item, maps: maps) { @@ -87,7 +85,7 @@ fn encode_inlined_item(ecx: @e::encode_ctxt, let id_range = ast_util::compute_id_range_for_inlined_item(ii); do ebml_w.wr_tag(c::tag_ast as uint) { - ast_util::serialize_id_range(ebml_w, id_range); + id_range.serialize(&ebml_w); encode_ast(ebml_w, simplify_ast(ii)); encode_side_tables_for_ii(ecx, maps, ebml_w, ii); } @@ -102,15 +100,15 @@ fn decode_inlined_item(cdata: cstore::crate_metadata, tcx: ty::ctxt, maps: maps, path: ast_map::path, - par_doc: ebml::Doc) -> Option { + par_doc: ebml2::Doc) -> Option { let dcx = @{cdata: cdata, tcx: tcx, maps: maps}; match par_doc.opt_child(c::tag_ast) { None => None, Some(ast_doc) => { debug!("> Decoding inlined fn: %s::?", ast_map::path_to_str(path, tcx.sess.parse_sess.interner)); - let ast_dsr = ebml::ebml_deserializer(ast_doc); - let from_id_range = ast_util::deserialize_id_range(ast_dsr); + let ast_dsr = &ebml2::Deserializer(ast_doc); + let from_id_range = deserialize(ast_dsr); let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range); let xcx = extended_decode_ctxt_(@{dcx: dcx, from_id_range: from_id_range, @@ -187,9 +185,9 @@ trait def_id_serializer_helpers { fn emit_def_id(did: ast::def_id); } -impl S: def_id_serializer_helpers { +impl S: def_id_serializer_helpers { fn emit_def_id(did: ast::def_id) { - ast::serialize_def_id(self, did) + did.serialize(&self) } } @@ -197,10 +195,10 @@ trait def_id_deserializer_helpers { fn read_def_id(xcx: extended_decode_ctxt) -> ast::def_id; } -impl D: def_id_deserializer_helpers { +impl D: def_id_deserializer_helpers { fn read_def_id(xcx: extended_decode_ctxt) -> ast::def_id { - let did = ast::deserialize_def_id(self); + let did: ast::def_id = deserialize(&self); did.tr(xcx) } } @@ -220,9 +218,9 @@ impl D: def_id_deserializer_helpers { // We also have to adjust the spans: for now we just insert a dummy span, // but eventually we should add entries to the local codemap as required. -fn encode_ast(ebml_w: ebml::Writer, item: ast::inlined_item) { +fn encode_ast(ebml_w: ebml2::Serializer, item: ast::inlined_item) { do ebml_w.wr_tag(c::tag_tree as uint) { - ast::serialize_inlined_item(ebml_w, item) + item.serialize(&ebml_w) } } @@ -280,10 +278,10 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { } } -fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item { +fn decode_ast(par_doc: ebml2::Doc) -> ast::inlined_item { let chi_doc = par_doc[c::tag_tree as uint]; - let d = ebml::ebml_deserializer(chi_doc); - ast::deserialize_inlined_item(d) + let d = &ebml2::Deserializer(chi_doc); + deserialize(d) } fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) @@ -334,13 +332,13 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) // ______________________________________________________________________ // Encoding and decoding of ast::def -fn encode_def(ebml_w: ebml::Writer, def: ast::def) { - ast::serialize_def(ebml_w, def) +fn encode_def(ebml_w: ebml2::Serializer, def: ast::def) { + def.serialize(&ebml_w) } -fn decode_def(xcx: extended_decode_ctxt, doc: ebml::Doc) -> ast::def { - let dsr = ebml::ebml_deserializer(doc); - let def = ast::deserialize_def(dsr); +fn decode_def(xcx: extended_decode_ctxt, doc: ebml2::Doc) -> ast::def { + let dsr = &ebml2::Deserializer(doc); + let def: ast::def = deserialize(dsr); def.tr(xcx) } @@ -425,17 +423,17 @@ impl ty::bound_region: tr { // ______________________________________________________________________ // Encoding and decoding of freevar information -fn encode_freevar_entry(ebml_w: ebml::Writer, fv: freevar_entry) { - serialize_freevar_entry(ebml_w, fv) +fn encode_freevar_entry(ebml_w: ebml2::Serializer, fv: @freevar_entry) { + (*fv).serialize(&ebml_w) } trait ebml_deserializer_helper { fn read_freevar_entry(xcx: extended_decode_ctxt) -> freevar_entry; } -impl ebml::EbmlDeserializer: ebml_deserializer_helper { +impl ebml2::Deserializer: ebml_deserializer_helper { fn read_freevar_entry(xcx: extended_decode_ctxt) -> freevar_entry { - let fv = deserialize_freevar_entry(self); + let fv: freevar_entry = deserialize(&self); fv.tr(xcx) } } @@ -454,28 +452,29 @@ trait read_method_map_entry_helper { } fn serialize_method_map_entry(ecx: @e::encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml2::Serializer, mme: method_map_entry) { do ebml_w.emit_rec { - do ebml_w.emit_rec_field(~"self_arg", 0u) { + do ebml_w.emit_field(~"self_arg", 0u) { ebml_w.emit_arg(ecx, mme.self_arg); } - do ebml_w.emit_rec_field(~"origin", 1u) { - typeck::serialize_method_origin(ebml_w, mme.origin); + do ebml_w.emit_field(~"origin", 1u) { + mme.origin.serialize(&ebml_w); } } } -impl ebml::EbmlDeserializer: read_method_map_entry_helper { +impl ebml2::Deserializer: read_method_map_entry_helper { fn read_method_map_entry(xcx: extended_decode_ctxt) -> method_map_entry { do self.read_rec { {self_arg: - self.read_rec_field(~"self_arg", 0u, || { + self.read_field(~"self_arg", 0u, || { self.read_arg(xcx) }), origin: - self.read_rec_field(~"origin", 1u, || { - typeck::deserialize_method_origin(self).tr(xcx) + self.read_field(~"origin", 1u, || { + let method_origin: method_origin = deserialize(&self); + method_origin.tr(xcx) })} } } @@ -504,19 +503,19 @@ impl method_origin: tr { // Encoding and decoding vtable_res fn encode_vtable_res(ecx: @e::encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml2::Serializer, dr: typeck::vtable_res) { // can't autogenerate this code because automatic serialization of // ty::t doesn't work, and there is no way (atm) to have // hand-written serialization routines combine with auto-generated // ones. perhaps we should fix this. do ebml_w.emit_from_vec(*dr) |vtable_origin| { - encode_vtable_origin(ecx, ebml_w, vtable_origin) + encode_vtable_origin(ecx, ebml_w, *vtable_origin) } } fn encode_vtable_origin(ecx: @e::encode_ctxt, - ebml_w: ebml::Writer, + ebml_w: ebml2::Serializer, vtable_origin: typeck::vtable_origin) { do ebml_w.emit_enum(~"vtable_origin") { match vtable_origin { @@ -563,7 +562,7 @@ trait vtable_deserialization_helpers { fn read_vtable_origin(xcx: extended_decode_ctxt) -> typeck::vtable_origin; } -impl ebml::EbmlDeserializer: vtable_deserialization_helpers { +impl ebml2::Deserializer: vtable_deserialization_helpers { fn read_vtable_res(xcx: extended_decode_ctxt) -> typeck::vtable_res { @self.read_to_vec(|| self.read_vtable_origin(xcx) ) } @@ -640,7 +639,7 @@ trait ebml_writer_helpers { fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty); } -impl ebml::Writer: ebml_writer_helpers { +impl ebml2::Serializer: ebml_writer_helpers { fn emit_ty(ecx: @e::encode_ctxt, ty: ty::t) { do self.emit_opaque { e::write_type(ecx, self, ty) @@ -661,7 +660,7 @@ impl ebml::Writer: ebml_writer_helpers { fn emit_tys(ecx: @e::encode_ctxt, tys: ~[ty::t]) { do self.emit_from_vec(tys) |ty| { - self.emit_ty(ecx, ty) + self.emit_ty(ecx, *ty) } } @@ -673,17 +672,15 @@ impl ebml::Writer: ebml_writer_helpers { fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty) { do self.emit_rec { - do self.emit_rec_field(~"bounds", 0u) { + do self.emit_field(~"bounds", 0u) { do self.emit_from_vec(*tpbt.bounds) |bs| { - self.emit_bounds(ecx, bs); + self.emit_bounds(ecx, *bs); } } - do self.emit_rec_field(~"region_param", 1u) { - ty::serialize_opt_region_variance( - self, - tpbt.region_param); + do self.emit_field(~"region_param", 1u) { + tpbt.region_param.serialize(&self); } - do self.emit_rec_field(~"ty", 2u) { + do self.emit_field(~"ty", 2u) { self.emit_ty(ecx, tpbt.ty); } } @@ -695,7 +692,7 @@ trait write_tag_and_id { fn id(id: ast::node_id); } -impl ebml::Writer: write_tag_and_id { +impl ebml2::Serializer: write_tag_and_id { fn tag(tag_id: c::astencode_tag, f: fn()) { do self.wr_tag(tag_id as uint) { f() } } @@ -707,7 +704,7 @@ impl ebml::Writer: write_tag_and_id { fn encode_side_tables_for_ii(ecx: @e::encode_ctxt, maps: maps, - ebml_w: ebml::Writer, + ebml_w: ebml2::Serializer, ii: ast::inlined_item) { do ebml_w.wr_tag(c::tag_table as uint) { ast_util::visit_ids_for_inlined_item( @@ -723,7 +720,7 @@ fn encode_side_tables_for_ii(ecx: @e::encode_ctxt, fn encode_side_tables_for_id(ecx: @e::encode_ctxt, maps: maps, - ebml_w: ebml::Writer, + ebml_w: ebml2::Serializer, id: ast::node_id) { let tcx = ecx.tcx; @@ -733,7 +730,7 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, do ebml_w.tag(c::tag_table_def) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - ast::serialize_def(ebml_w, *def) + (*def).serialize(&ebml_w) } } } @@ -810,7 +807,7 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { do ebml_w.emit_from_vec((*m).get()) |id| { - ebml_w.emit_int(id); + id.serialize(&ebml_w); } } } @@ -838,7 +835,7 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, do ebml_w.tag(c::tag_table_adjustments) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - ty::serialize_AutoAdjustment(ebml_w, **adj) + (**adj).serialize(&ebml_w) } } } @@ -852,13 +849,13 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, trait doc_decoder_helpers { fn as_int() -> int; - fn opt_child(tag: c::astencode_tag) -> Option; + fn opt_child(tag: c::astencode_tag) -> Option; } -impl ebml::Doc: doc_decoder_helpers { - fn as_int() -> int { ebml::doc_as_u64(self) as int } - fn opt_child(tag: c::astencode_tag) -> Option { - ebml::maybe_get_doc(self, tag as uint) +impl ebml2::Doc: doc_decoder_helpers { + fn as_int() -> int { ebml2::doc_as_u64(self) as int } + fn opt_child(tag: c::astencode_tag) -> Option { + ebml2::maybe_get_doc(self, tag as uint) } } @@ -871,7 +868,7 @@ trait ebml_deserializer_decoder_helpers { -> ty::ty_param_bounds_and_ty; } -impl ebml::EbmlDeserializer: ebml_deserializer_decoder_helpers { +impl ebml2::Deserializer: ebml_deserializer_decoder_helpers { fn read_arg(xcx: extended_decode_ctxt) -> ty::arg { do self.read_opaque |doc| { @@ -911,13 +908,13 @@ impl ebml::EbmlDeserializer: ebml_deserializer_decoder_helpers { { do self.read_rec { { - bounds: self.read_rec_field(~"bounds", 0u, || { + bounds: self.read_field(~"bounds", 0u, || { @self.read_to_vec(|| self.read_bounds(xcx) ) }), - region_param: self.read_rec_field(~"region_param", 1u, || { - ty::deserialize_opt_region_variance(self) + region_param: self.read_field(~"region_param", 1u, || { + deserialize(&self) }), - ty: self.read_rec_field(~"ty", 2u, || { + ty: self.read_field(~"ty", 2u, || { self.read_ty(xcx) }) } @@ -926,10 +923,10 @@ impl ebml::EbmlDeserializer: ebml_deserializer_decoder_helpers { } fn decode_side_tables(xcx: extended_decode_ctxt, - ast_doc: ebml::Doc) { + ast_doc: ebml2::Doc) { let dcx = xcx.dcx; let tbl_doc = ast_doc[c::tag_table as uint]; - for ebml::docs(tbl_doc) |tag, entry_doc| { + for ebml2::docs(tbl_doc) |tag, entry_doc| { let id0 = entry_doc[c::tag_table_id as uint].as_int(); let id = xcx.tr_id(id0); @@ -943,7 +940,7 @@ fn decode_side_tables(xcx: extended_decode_ctxt, dcx.tcx.legacy_boxed_traits.insert(id, ()); } else { let val_doc = entry_doc[c::tag_table_val as uint]; - let val_dsr = ebml::ebml_deserializer(val_doc); + let val_dsr = &ebml2::Deserializer(val_doc); if tag == (c::tag_table_def as uint) { let def = decode_def(xcx, val_doc); dcx.tcx.def_map.insert(id, def); @@ -979,7 +976,8 @@ fn decode_side_tables(xcx: extended_decode_ctxt, dcx.maps.vtable_map.insert(id, val_dsr.read_vtable_res(xcx)); } else if tag == (c::tag_table_adjustments as uint) { - let adj = @ty::deserialize_AutoAdjustment(val_dsr).tr(xcx); + let adj: @ty::AutoAdjustment = @deserialize(val_dsr); + adj.tr(xcx); dcx.tcx.adjustments.insert(id, adj); } else { xcx.dcx.tcx.sess.bug( @@ -995,17 +993,17 @@ fn decode_side_tables(xcx: extended_decode_ctxt, // Testing of astencode_gen #[cfg(test)] -fn encode_item_ast(ebml_w: ebml::Writer, item: @ast::item) { +fn encode_item_ast(ebml_w: ebml2::Serializer, item: @ast::item) { do ebml_w.wr_tag(c::tag_tree as uint) { - ast::serialize_item(ebml_w, *item); + (*item).serialize(&ebml_w) } } #[cfg(test)] -fn decode_item_ast(par_doc: ebml::Doc) -> @ast::item { +fn decode_item_ast(par_doc: ebml2::Doc) -> @ast::item { let chi_doc = par_doc[c::tag_tree as uint]; - let d = ebml::ebml_deserializer(chi_doc); - @ast::deserialize_item(d) + let d = &ebml2::Deserializer(chi_doc); + @deserialize(d) } #[cfg(test)] @@ -1031,16 +1029,18 @@ fn mk_ctxt() -> fake_ext_ctxt { #[cfg(test)] fn roundtrip(in_item: @ast::item) { let bytes = do io::with_bytes_writer |wr| { - let ebml_w = ebml::Writer(wr); + let ebml_w = ebml2::Serializer(wr); encode_item_ast(ebml_w, in_item); }; - let ebml_doc = ebml::Doc(@bytes); + let ebml_doc = ebml2::Doc(@bytes); let out_item = decode_item_ast(ebml_doc); - let exp_str = - io::with_str_writer(|w| ast::serialize_item(w, *in_item) ); - let out_str = - io::with_str_writer(|w| ast::serialize_item(w, *out_item) ); + let exp_str = do io::with_str_writer |w| { + in_item.serialize(&std::prettyprint2::Serializer(w)) + }; + let out_str = do io::with_str_writer |w| { + out_item.serialize(&std::prettyprint2::Serializer(w)) + }; debug!("expected string: %s", exp_str); debug!("actual string : %s", out_str); diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index 7e925d7d8d84..d26b9566c97e 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -5,19 +5,19 @@ use syntax::print::pprust::path_to_str; use std::map::*; use option::*; use syntax::{ast, ast_util, visit}; -use syntax::ast::{serialize_span, deserialize_span}; use syntax::codemap::span; export annotate_freevars; export freevar_map; export freevar_info; -export freevar_entry, serialize_freevar_entry, deserialize_freevar_entry; +export freevar_entry; export get_freevars; export has_freevars; // A vector of defs representing the free variables referred to in a function. // (The def_upvar will already have been stripped). -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type freevar_entry = { def: ast::def, //< The variable being accessed free. span: span //< First span where it is accessed (there can be multiple) diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index f2f7b32b6706..bbc3a06fb675 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -18,10 +18,6 @@ use middle::lint::{get_lint_level, allow}; use syntax::ast::*; use syntax::print::pprust::*; use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str}; -use std::serialization::{serialize_Option, - deserialize_Option, - serialize_uint, - deserialize_uint}; export TyVid, IntVid, FnVid, RegionVid, vid; export br_hashmap; @@ -173,7 +169,6 @@ export mach_sty; export ty_sort_str; export normalize_ty; export to_str; -export borrow, serialize_borrow, deserialize_borrow; export bound_const; export terr_no_integral_type, terr_ty_param_size, terr_self_substs; export terr_in_field, terr_record_fields, terr_vstores_differ, terr_arg_count; @@ -192,12 +187,10 @@ export is_blockish; export method_call_bounds; export hash_region; export region_variance, rv_covariant, rv_invariant, rv_contravariant; -export serialize_region_variance, deserialize_region_variance; export opt_region_variance; -export serialize_opt_region_variance, deserialize_opt_region_variance; export determine_inherited_purity; export provided_trait_methods; -export AutoAdjustment, serialize_AutoAdjustment, deserialize_AutoAdjustment; +export AutoAdjustment; export AutoRef, AutoRefKind, AutoSlice, AutoPtr; // Data types @@ -218,7 +211,8 @@ type method = {ident: ast::ident, type mt = {ty: t, mutbl: ast::mutability}; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum vstore { vstore_fixed(uint), vstore_uniq, @@ -275,10 +269,10 @@ enum ast_ty_to_ty_cache_entry { atttce_resolved(t) /* resolved to a type, irrespective of region */ } -#[auto_serialize] type opt_region_variance = Option; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum region_variance { rv_covariant, rv_invariant, rv_contravariant } impl region_variance : cmp::Eq { @@ -295,20 +289,23 @@ impl region_variance : cmp::Eq { pure fn ne(other: ®ion_variance) -> bool { !self.eq(other) } } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type AutoAdjustment = { autoderefs: uint, autoref: Option }; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type AutoRef = { kind: AutoRefKind, region: region, mutbl: ast::mutability }; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum AutoRefKind { /// Convert from @[]/~[] to &[] (or str) AutoSlice, @@ -512,7 +509,8 @@ impl param_ty : to_bytes::IterBytes { /// Representation of regions: -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions @@ -540,7 +538,8 @@ enum region { re_var(RegionVid) } -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum bound_region { /// The self region for classes, impls (&T in a type defn or &self/T) br_self, @@ -670,7 +669,8 @@ enum param_bound { enum TyVid = uint; enum IntVid = uint; enum FnVid = uint; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum RegionVid = uint; enum InferTy { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 514fc2cfbb32..c2bd7f26bade 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -56,7 +56,6 @@ use middle::ty::{vstore_uniq}; use std::smallintmap; use std::map; use std::map::HashMap; -use std::serialization::{serialize_uint, deserialize_uint}; use syntax::print::pprust::*; use util::ppaux::{ty_to_str, tys_to_str, region_to_str, bound_region_to_str, vstore_to_str, expr_repr}; @@ -67,9 +66,8 @@ use list::{List, Nil, Cons}; export check_crate; export infer; export method_map; -export method_origin, serialize_method_origin, deserialize_method_origin; -export method_map_entry, serialize_method_map_entry; -export deserialize_method_map_entry; +export method_origin; +export method_map_entry; export vtable_map; export vtable_res; export vtable_origin; @@ -77,7 +75,8 @@ export method_static, method_param, method_trait, method_self; export vtable_static, vtable_param, vtable_trait; export provided_methods_map; -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] enum method_origin { // fully statically resolved method method_static(ast::def_id), @@ -94,7 +93,8 @@ enum method_origin { // details for a method invoked with a receiver whose type is a type parameter // with a bounded trait. -#[auto_serialize] +#[auto_serialize2] +#[auto_deserialize2] type method_param = { // the trait containing the method to be invoked trait_id: ast::def_id, From d301dd3686ddd04845c1e9f5b9254aa3498a8a7b Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sun, 7 Oct 2012 14:56:18 -0700 Subject: [PATCH 015/292] remove the old auto_serialize syntax extension --- src/libsyntax/ext/auto_serialize.rs | 109 +------------- src/libsyntax/ext/auto_serialize2.rs | 80 +++++++++++ src/libsyntax/ext/base.rs | 64 +++++++++ src/libsyntax/syntax.rc | 1 + src/test/run-pass/auto_serialize.rs | 208 --------------------------- 5 files changed, 146 insertions(+), 316 deletions(-) delete mode 100644 src/test/run-pass/auto_serialize.rs diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 64915c607425..63a6551bf888 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -122,34 +122,7 @@ fn expand(cx: ext_ctxt, } } -trait ext_ctxt_helpers { - fn helper_path(base_path: @ast::path, helper_name: ~str) -> @ast::path; - fn path(span: span, strs: ~[ast::ident]) -> @ast::path; - fn path_tps(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::path; - fn ty_path(span: span, strs: ~[ast::ident], tps: ~[@ast::ty]) -> @ast::ty; - fn ty_fn(span: span, - -input_tys: ~[@ast::ty], - -output: @ast::ty) -> @ast::ty; - fn ty_nil(span: span) -> @ast::ty; - fn expr(span: span, node: ast::expr_) -> @ast::expr; - fn var_ref(span: span, name: ast::ident) -> @ast::expr; - fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk; - fn expr_blk(expr: @ast::expr) -> ast::blk; - fn binder_pat(span: span, nm: ast::ident) -> @ast::pat; - fn stmt(expr: @ast::expr) -> @ast::stmt; - fn alt_stmt(arms: ~[ast::arm], span: span, -v: @ast::expr) -> @ast::stmt; - fn lit_str(span: span, s: @~str) -> @ast::expr; - fn lit_uint(span: span, i: uint) -> @ast::expr; - fn lambda(blk: ast::blk) -> @ast::expr; - fn clone_folder() -> fold::ast_fold; - fn clone(v: @ast::expr) -> @ast::expr; - fn clone_ty(v: @ast::ty) -> @ast::ty; - fn clone_ty_param(v: ast::ty_param) -> ast::ty_param; - fn at(span: span, expr: @ast::expr) -> @ast::expr; -} - -impl ext_ctxt: ext_ctxt_helpers { +priv impl ext_ctxt { fn helper_path(base_path: @ast::path, helper_name: ~str) -> @ast::path { let head = vec::init(base_path.idents); @@ -162,22 +135,6 @@ impl ext_ctxt: ext_ctxt_helpers { tail)))])) } - fn path(span: span, strs: ~[ast::ident]) -> @ast::path { - @{span: span, global: false, idents: strs, rp: None, types: ~[]} - } - - fn path_tps(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::path { - @{span: span, global: false, idents: strs, rp: None, types: tps} - } - - fn ty_path(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::ty { - @{id: self.next_id(), - node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), - span: span} - } - fn ty_fn(span: span, -input_tys: ~[@ast::ty], -output: @ast::ty) -> @ast::ty { @@ -202,48 +159,10 @@ impl ext_ctxt: ext_ctxt_helpers { @{id: self.next_id(), node: ast::ty_nil, span: span} } - fn expr(span: span, node: ast::expr_) -> @ast::expr { - @{id: self.next_id(), callee_id: self.next_id(), - node: node, span: span} - } - fn var_ref(span: span, name: ast::ident) -> @ast::expr { self.expr(span, ast::expr_path(self.path(span, ~[name]))) } - fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk { - {node: {view_items: ~[], - stmts: stmts, - expr: None, - id: self.next_id(), - rules: ast::default_blk}, - span: span} - } - - fn expr_blk(expr: @ast::expr) -> ast::blk { - {node: {view_items: ~[], - stmts: ~[], - expr: Some(expr), - id: self.next_id(), - rules: ast::default_blk}, - span: expr.span} - } - - fn binder_pat(span: span, nm: ast::ident) -> @ast::pat { - let path = @{span: span, global: false, idents: ~[nm], - rp: None, types: ~[]}; - @{id: self.next_id(), - node: ast::pat_ident(ast::bind_by_implicit_ref, - path, - None), - span: span} - } - - fn stmt(expr: @ast::expr) -> @ast::stmt { - @{node: ast::stmt_semi(expr, self.next_id()), - span: expr.span} - } - fn alt_stmt(arms: ~[ast::arm], span: span, -v: @ast::expr) -> @ast::stmt { self.stmt( @@ -252,32 +171,6 @@ impl ext_ctxt: ext_ctxt_helpers { ast::expr_match(v, arms))) } - fn lit_str(span: span, s: @~str) -> @ast::expr { - self.expr( - span, - ast::expr_vstore( - self.expr( - span, - ast::expr_lit( - @{node: ast::lit_str(s), - span: span})), - ast::expr_vstore_uniq)) - } - - fn lit_uint(span: span, i: uint) -> @ast::expr { - self.expr( - span, - ast::expr_lit( - @{node: ast::lit_uint(i as u64, ast::ty_u), - span: span})) - } - - fn lambda(blk: ast::blk) -> @ast::expr { - let ext_cx = self; - let blk_e = self.expr(blk.span, ast::expr_block(blk)); - #ast{ || $(blk_e) } - } - fn clone_folder() -> fold::ast_fold { fold::make_fold(@{ new_id: |_id| self.next_id(), diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs index 99f837a4c844..ba48b0d3f5fa 100644 --- a/src/libsyntax/ext/auto_serialize2.rs +++ b/src/libsyntax/ext/auto_serialize2.rs @@ -215,6 +215,86 @@ fn expand_auto_deserialize( } priv impl ext_ctxt { + fn expr(span: span, node: ast::expr_) -> @ast::expr { + @{id: self.next_id(), callee_id: self.next_id(), + node: node, span: span} + } + + fn path(span: span, strs: ~[ast::ident]) -> @ast::path { + @{span: span, global: false, idents: strs, rp: None, types: ~[]} + } + + fn path_tps(span: span, strs: ~[ast::ident], + tps: ~[@ast::ty]) -> @ast::path { + @{span: span, global: false, idents: strs, rp: None, types: tps} + } + + fn ty_path(span: span, strs: ~[ast::ident], + tps: ~[@ast::ty]) -> @ast::ty { + @{id: self.next_id(), + node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), + span: span} + } + + fn binder_pat(span: span, nm: ast::ident) -> @ast::pat { + let path = @{span: span, global: false, idents: ~[nm], + rp: None, types: ~[]}; + @{id: self.next_id(), + node: ast::pat_ident(ast::bind_by_implicit_ref, + path, + None), + span: span} + } + + fn stmt(expr: @ast::expr) -> @ast::stmt { + @{node: ast::stmt_semi(expr, self.next_id()), + span: expr.span} + } + + fn lit_str(span: span, s: @~str) -> @ast::expr { + self.expr( + span, + ast::expr_vstore( + self.expr( + span, + ast::expr_lit( + @{node: ast::lit_str(s), + span: span})), + ast::expr_vstore_uniq)) + } + + fn lit_uint(span: span, i: uint) -> @ast::expr { + self.expr( + span, + ast::expr_lit( + @{node: ast::lit_uint(i as u64, ast::ty_u), + span: span})) + } + + fn lambda(blk: ast::blk) -> @ast::expr { + let ext_cx = self; + let blk_e = self.expr(blk.span, ast::expr_block(blk)); + #ast{ || $(blk_e) } + } + + fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk { + {node: {view_items: ~[], + stmts: stmts, + expr: None, + id: self.next_id(), + rules: ast::default_blk}, + span: span} + } + + fn expr_blk(expr: @ast::expr) -> ast::blk { + {node: {view_items: ~[], + stmts: ~[], + expr: Some(expr), + id: self.next_id(), + rules: ast::default_blk}, + span: expr.span} + } + fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr { self.expr(span, ast::expr_path(self.path(span, strs))) } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 53880baea9b8..794c5233e21e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -64,6 +64,7 @@ enum syntax_extension { // A temporary hard-coded map of methods for expanding syntax extension // AST nodes into full ASTs +#[cfg(stage0)] fn syntax_expander_table() -> HashMap<~str, syntax_extension> { fn builtin(f: syntax_expander_) -> syntax_extension {normal({expander: f, span: None})} @@ -122,6 +123,69 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { return syntax_expanders; } +#[cfg(stage1)] +#[cfg(stage2)] +fn syntax_expander_table() -> HashMap<~str, syntax_extension> { + fn builtin(f: syntax_expander_) -> syntax_extension + {normal({expander: f, span: None})} + fn builtin_expr_tt(f: syntax_expander_tt_) -> syntax_extension { + expr_tt({expander: f, span: None}) + } + fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension { + item_tt({expander: f, span: None}) + } + let syntax_expanders = HashMap(); + syntax_expanders.insert(~"macro", + macro_defining(ext::simplext::add_new_extension)); + syntax_expanders.insert(~"macro_rules", + builtin_item_tt( + ext::tt::macro_rules::add_new_extension)); + syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); + syntax_expanders.insert( + ~"auto_serialize", + item_decorator(ext::auto_serialize2::expand_auto_serialize)); + syntax_expanders.insert( + ~"auto_deserialize", + item_decorator(ext::auto_serialize2::expand_auto_deserialize)); + syntax_expanders.insert( + ~"auto_serialize2", + item_decorator(ext::auto_serialize2::expand_auto_serialize)); + syntax_expanders.insert( + ~"auto_deserialize2", + item_decorator(ext::auto_serialize2::expand_auto_deserialize)); + syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext)); + syntax_expanders.insert(~"concat_idents", + builtin(ext::concat_idents::expand_syntax_ext)); + syntax_expanders.insert(~"ident_to_str", + builtin(ext::ident_to_str::expand_syntax_ext)); + syntax_expanders.insert(~"log_syntax", + builtin_expr_tt( + ext::log_syntax::expand_syntax_ext)); + syntax_expanders.insert(~"ast", + builtin(ext::qquote::expand_ast)); + syntax_expanders.insert(~"line", + builtin(ext::source_util::expand_line)); + syntax_expanders.insert(~"col", + builtin(ext::source_util::expand_col)); + syntax_expanders.insert(~"file", + builtin(ext::source_util::expand_file)); + syntax_expanders.insert(~"stringify", + builtin(ext::source_util::expand_stringify)); + syntax_expanders.insert(~"include", + builtin(ext::source_util::expand_include)); + syntax_expanders.insert(~"include_str", + builtin(ext::source_util::expand_include_str)); + syntax_expanders.insert(~"include_bin", + builtin(ext::source_util::expand_include_bin)); + syntax_expanders.insert(~"module_path", + builtin(ext::source_util::expand_mod)); + syntax_expanders.insert(~"proto", + builtin_item_tt(ext::pipes::expand_proto)); + syntax_expanders.insert( + ~"trace_macros", + builtin_expr_tt(ext::trace_macros::expand_trace_macros)); + return syntax_expanders; +} // One of these is made during expansion and incrementally updated as we go; // when a macro expansion occurs, the resulting nodes have the backtrace() diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 38abf5f445c2..4a6bac9cd64b 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -128,6 +128,7 @@ mod ext { mod ident_to_str; #[legacy_exports] mod log_syntax; + #[cfg(stage0)] #[legacy_exports] mod auto_serialize; #[legacy_exports] diff --git a/src/test/run-pass/auto_serialize.rs b/src/test/run-pass/auto_serialize.rs deleted file mode 100644 index 3a07faa75c5e..000000000000 --- a/src/test/run-pass/auto_serialize.rs +++ /dev/null @@ -1,208 +0,0 @@ -// xfail-fast -#[legacy_modes]; - -extern mod std; - -// These tests used to be separate files, but I wanted to refactor all -// the common code. - -use cmp::Eq; -use std::ebml; -use io::Writer; -use std::serialization::{serialize_uint, deserialize_uint}; - -fn test_ser_and_deser(a1: A, - expected: ~str, - ebml_ser_fn: fn(ebml::Writer, A), - ebml_deser_fn: fn(ebml::EbmlDeserializer) -> A, - io_ser_fn: fn(io::Writer, A)) { - - // check the pretty printer: - io_ser_fn(io::stdout(), a1); - let s = io::with_str_writer(|w| io_ser_fn(w, a1) ); - debug!("s == %?", s); - assert s == expected; - - // check the EBML serializer: - let bytes = do io::with_bytes_writer |wr| { - let w = ebml::Writer(wr); - ebml_ser_fn(w, a1); - }; - let d = ebml::Doc(@bytes); - let a2 = ebml_deser_fn(ebml::ebml_deserializer(d)); - io::print(~"\na1 = "); - io_ser_fn(io::stdout(), a1); - io::print(~"\na2 = "); - io_ser_fn(io::stdout(), a2); - io::print(~"\n"); - assert a1 == a2; - -} - -#[auto_serialize] -enum expr { - val(uint), - plus(@expr, @expr), - minus(@expr, @expr) -} - -impl an_enum : cmp::Eq { - pure fn eq(other: &an_enum) -> bool { - self.v == (*other).v - } - pure fn ne(other: &an_enum) -> bool { !self.eq(other) } -} - -impl point : cmp::Eq { - pure fn eq(other: &point) -> bool { - self.x == (*other).x && self.y == (*other).y - } - pure fn ne(other: &point) -> bool { !self.eq(other) } -} - -impl quark : cmp::Eq { - pure fn eq(other: &quark) -> bool { - match self { - top(ref q) => match (*other) { - top(ref r) => q == r, - bottom(_) => false - }, - bottom(ref q) => match (*other) { - top(_) => false, - bottom(ref r) => q == r - } - } - } - pure fn ne(other: &quark) -> bool { !self.eq(other) } -} - - -impl c_like : cmp::Eq { - pure fn eq(other: &c_like) -> bool { - self as int == (*other) as int - } - pure fn ne(other: &c_like) -> bool { !self.eq(other) } -} - -impl expr : cmp::Eq { - pure fn eq(other: &expr) -> bool { - match self { - val(e0a) => { - match (*other) { - val(e0b) => e0a == e0b, - _ => false - } - } - plus(e0a, e1a) => { - match (*other) { - plus(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - minus(e0a, e1a) => { - match (*other) { - minus(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - } - } - pure fn ne(other: &expr) -> bool { !self.eq(other) } -} - -#[auto_serialize] -type spanned = {lo: uint, hi: uint, node: T}; - -impl spanned : cmp::Eq { - pure fn eq(other: &spanned) -> bool { - self.lo == (*other).lo && self.hi == (*other).hi && - self.node.eq(&(*other).node) - } - pure fn ne(other: &spanned) -> bool { !self.eq(other) } -} - -#[auto_serialize] -type spanned_uint = spanned; - -#[auto_serialize] -type some_rec = {v: uint_vec}; - -#[auto_serialize] -enum an_enum = some_rec; - -#[auto_serialize] -type uint_vec = ~[uint]; - -#[auto_serialize] -type point = {x: uint, y: uint}; - -#[auto_serialize] -enum quark { - top(T), - bottom(T) -} - -#[auto_serialize] -type uint_quark = quark; - -#[auto_serialize] -enum c_like { a, b, c } - -fn main() { - - test_ser_and_deser(plus(@minus(@val(3u), @val(10u)), - @plus(@val(22u), @val(5u))), - ~"plus(@minus(@val(3u), @val(10u)), \ - @plus(@val(22u), @val(5u)))", - serialize_expr, - deserialize_expr, - serialize_expr); - - test_ser_and_deser({lo: 0u, hi: 5u, node: 22u}, - ~"{lo: 0u, hi: 5u, node: 22u}", - serialize_spanned_uint, - deserialize_spanned_uint, - serialize_spanned_uint); - - test_ser_and_deser(an_enum({v: ~[1u, 2u, 3u]}), - ~"an_enum({v: [1u, 2u, 3u]})", - serialize_an_enum, - deserialize_an_enum, - serialize_an_enum); - - test_ser_and_deser({x: 3u, y: 5u}, - ~"{x: 3u, y: 5u}", - serialize_point, - deserialize_point, - serialize_point); - - test_ser_and_deser(~[1u, 2u, 3u], - ~"[1u, 2u, 3u]", - serialize_uint_vec, - deserialize_uint_vec, - serialize_uint_vec); - - test_ser_and_deser(top(22u), - ~"top(22u)", - serialize_uint_quark, - deserialize_uint_quark, - serialize_uint_quark); - - test_ser_and_deser(bottom(222u), - ~"bottom(222u)", - serialize_uint_quark, - deserialize_uint_quark, - serialize_uint_quark); - - test_ser_and_deser(a, - ~"a", - serialize_c_like, - deserialize_c_like, - serialize_c_like); - - test_ser_and_deser(b, - ~"b", - serialize_c_like, - deserialize_c_like, - serialize_c_like); -} From eb626e71199d1d89a0242043f096d89941fa2ec7 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sun, 7 Oct 2012 16:33:20 -0700 Subject: [PATCH 016/292] Remove the old serializers (needs snapshot) --- src/libstd/ebml.rs | 398 ++-- src/libstd/ebml2.rs | 645 +------ src/libstd/json.rs | 10 +- src/libstd/prettyprint.rs | 180 +- src/libstd/prettyprint2.rs | 177 +- src/libstd/serialization.rs | 764 +++++--- src/libstd/serialization2.rs | 558 +----- src/libsyntax/ast.rs | 178 +- src/libsyntax/ast_util.rs | 2 + src/libsyntax/ext/auto_serialize.rs | 1695 ++++++++++------- src/libsyntax/ext/auto_serialize2.rs | 114 -- src/libsyntax/ext/base.rs | 12 +- src/libsyntax/parse/token.rs | 6 + src/libsyntax/syntax.rc | 2 +- src/rustc/metadata/decoder.rs | 245 +-- src/rustc/metadata/encoder.rs | 80 +- src/rustc/middle/astencode.rs | 91 +- src/rustc/middle/freevars.rs | 2 + src/rustc/middle/ty.rs | 16 + src/rustc/middle/typeck.rs | 4 + .../{auto_serialize2.rs => auto_serialize.rs} | 42 +- 21 files changed, 2265 insertions(+), 2956 deletions(-) rename src/test/run-pass/{auto_serialize2.rs => auto_serialize.rs} (86%) diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 3df5a70a0c1f..79e491e309bc 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -1,21 +1,35 @@ #[forbid(deprecated_mode)]; +use serialization; + // Simple Extensible Binary Markup Language (ebml) reader and writer on a // cursor model. See the specification here: // http://www.matroska.org/technical/specs/rfc/index.html -use core::Option; -use option::{Some, None}; -type EbmlTag = {id: uint, size: uint}; +struct EbmlTag { + id: uint, + size: uint, +} -type EbmlState = {ebml_tag: EbmlTag, tag_pos: uint, data_pos: uint}; +struct EbmlState { + ebml_tag: EbmlTag, + tag_pos: uint, + data_pos: uint, +} // FIXME (#2739): When we have module renaming, make "reader" and "writer" // separate modules within this file. // ebml reading -pub type Doc = {data: @~[u8], start: uint, end: uint}; +struct Doc { + data: @~[u8], + start: uint, + end: uint, +} -type TaggedDoc = {tag: uint, doc: Doc}; +struct TaggedDoc { + tag: uint, + doc: Doc, +} impl Doc: ops::Index { pure fn index(tag: uint) -> Doc { @@ -49,15 +63,17 @@ fn vuint_at(data: &[u8], start: uint) -> {val: uint, next: uint} { } pub fn Doc(data: @~[u8]) -> Doc { - return {data: data, start: 0u, end: vec::len::(*data)}; + Doc { data: data, start: 0u, end: vec::len::(*data) } } pub fn doc_at(data: @~[u8], start: uint) -> TaggedDoc { let elt_tag = vuint_at(*data, start); let elt_size = vuint_at(*data, elt_tag.next); let end = elt_size.next + elt_size.val; - return {tag: elt_tag.val, - doc: {data: data, start: elt_size.next, end: end}}; + TaggedDoc { + tag: elt_tag.val, + doc: Doc { data: data, start: elt_size.next, end: end } + } } pub fn maybe_get_doc(d: Doc, tg: uint) -> Option { @@ -67,19 +83,15 @@ pub fn maybe_get_doc(d: Doc, tg: uint) -> Option { let elt_size = vuint_at(*d.data, elt_tag.next); pos = elt_size.next + elt_size.val; if elt_tag.val == tg { - return Some::({ - data: d.data, - start: elt_size.next, - end: pos - }); + return Some(Doc { data: d.data, start: elt_size.next, end: pos }); } } - return None::; + None } pub fn get_doc(d: Doc, tg: uint) -> Doc { match maybe_get_doc(d, tg) { - Some(d) => return d, + Some(d) => d, None => { error!("failed to find block with tag %u", tg); fail; @@ -93,7 +105,8 @@ pub fn docs(d: Doc, it: fn(uint, Doc) -> bool) { let elt_tag = vuint_at(*d.data, pos); let elt_size = vuint_at(*d.data, elt_tag.next); pos = elt_size.next + elt_size.val; - if !it(elt_tag.val, {data: d.data, start: elt_size.next, end: pos}) { + let doc = Doc { data: d.data, start: elt_size.next, end: pos }; + if !it(elt_tag.val, doc) { break; } } @@ -106,7 +119,8 @@ pub fn tagged_docs(d: Doc, tg: uint, it: fn(Doc) -> bool) { let elt_size = vuint_at(*d.data, elt_tag.next); pos = elt_size.next + elt_size.val; if elt_tag.val == tg { - if !it({data: d.data, start: elt_size.next, end: pos}) { + let doc = Doc { data: d.data, start: elt_size.next, end: pos }; + if !it(doc) { break; } } @@ -116,29 +130,29 @@ pub fn tagged_docs(d: Doc, tg: uint, it: fn(Doc) -> bool) { pub fn doc_data(d: Doc) -> ~[u8] { vec::slice::(*d.data, d.start, d.end) } pub fn with_doc_data(d: Doc, f: fn(x: &[u8]) -> T) -> T { - return f(vec::view(*d.data, d.start, d.end)); + f(vec::view(*d.data, d.start, d.end)) } -pub fn doc_as_str(d: Doc) -> ~str { return str::from_bytes(doc_data(d)); } +pub fn doc_as_str(d: Doc) -> ~str { str::from_bytes(doc_data(d)) } pub fn doc_as_u8(d: Doc) -> u8 { assert d.end == d.start + 1u; - return (*d.data)[d.start]; + (*d.data)[d.start] } pub fn doc_as_u16(d: Doc) -> u16 { assert d.end == d.start + 2u; - return io::u64_from_be_bytes(*d.data, d.start, 2u) as u16; + io::u64_from_be_bytes(*d.data, d.start, 2u) as u16 } pub fn doc_as_u32(d: Doc) -> u32 { assert d.end == d.start + 4u; - return io::u64_from_be_bytes(*d.data, d.start, 4u) as u32; + io::u64_from_be_bytes(*d.data, d.start, 4u) as u32 } pub fn doc_as_u64(d: Doc) -> u64 { assert d.end == d.start + 8u; - return io::u64_from_be_bytes(*d.data, d.start, 8u); + io::u64_from_be_bytes(*d.data, d.start, 8u) } pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 } @@ -147,10 +161,9 @@ pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 } pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 } // ebml writing -type Writer_ = {writer: io::Writer, mut size_positions: ~[uint]}; - -pub enum Writer { - Writer_(Writer_) +struct Serializer { + writer: io::Writer, + priv mut size_positions: ~[uint], } fn write_sized_vuint(w: io::Writer, n: uint, size: uint) { @@ -173,13 +186,13 @@ fn write_vuint(w: io::Writer, n: uint) { fail fmt!("vint to write too big: %?", n); } -pub fn Writer(w: io::Writer) -> Writer { +pub fn Serializer(w: io::Writer) -> Serializer { let size_positions: ~[uint] = ~[]; - return Writer_({writer: w, mut size_positions: size_positions}); + Serializer { writer: w, mut size_positions: size_positions } } // FIXME (#2741): Provide a function to write the standard ebml header. -impl Writer { +impl Serializer { fn start_tag(tag_id: uint) { debug!("Start tag %u", tag_id); @@ -295,12 +308,7 @@ enum EbmlSerializerTag { EsLabel // Used only when debugging } -trait SerializerPriv { - fn _emit_tagged_uint(t: EbmlSerializerTag, v: uint); - fn _emit_label(label: &str); -} - -impl ebml::Writer: SerializerPriv { +priv impl Serializer { // used internally to emit things like the vector length and so on fn _emit_tagged_uint(t: EbmlSerializerTag, v: uint) { assert v <= 0xFFFF_FFFF_u; @@ -318,89 +326,123 @@ impl ebml::Writer: SerializerPriv { } } -impl ebml::Writer { - fn emit_opaque(f: fn()) { +impl Serializer { + fn emit_opaque(&self, f: fn()) { do self.wr_tag(EsOpaque as uint) { f() } } } -impl ebml::Writer: serialization::Serializer { - fn emit_nil() {} +impl Serializer: serialization::Serializer { + fn emit_nil(&self) {} - fn emit_uint(v: uint) { self.wr_tagged_u64(EsUint as uint, v as u64); } - fn emit_u64(v: u64) { self.wr_tagged_u64(EsU64 as uint, v); } - fn emit_u32(v: u32) { self.wr_tagged_u32(EsU32 as uint, v); } - fn emit_u16(v: u16) { self.wr_tagged_u16(EsU16 as uint, v); } - fn emit_u8(v: u8) { self.wr_tagged_u8 (EsU8 as uint, v); } + fn emit_uint(&self, v: uint) { + self.wr_tagged_u64(EsUint as uint, v as u64); + } + fn emit_u64(&self, v: u64) { self.wr_tagged_u64(EsU64 as uint, v); } + fn emit_u32(&self, v: u32) { self.wr_tagged_u32(EsU32 as uint, v); } + fn emit_u16(&self, v: u16) { self.wr_tagged_u16(EsU16 as uint, v); } + fn emit_u8(&self, v: u8) { self.wr_tagged_u8 (EsU8 as uint, v); } - fn emit_int(v: int) { self.wr_tagged_i64(EsInt as uint, v as i64); } - fn emit_i64(v: i64) { self.wr_tagged_i64(EsI64 as uint, v); } - fn emit_i32(v: i32) { self.wr_tagged_i32(EsI32 as uint, v); } - fn emit_i16(v: i16) { self.wr_tagged_i16(EsI16 as uint, v); } - fn emit_i8(v: i8) { self.wr_tagged_i8 (EsI8 as uint, v); } + fn emit_int(&self, v: int) { + self.wr_tagged_i64(EsInt as uint, v as i64); + } + fn emit_i64(&self, v: i64) { self.wr_tagged_i64(EsI64 as uint, v); } + fn emit_i32(&self, v: i32) { self.wr_tagged_i32(EsI32 as uint, v); } + fn emit_i16(&self, v: i16) { self.wr_tagged_i16(EsI16 as uint, v); } + fn emit_i8(&self, v: i8) { self.wr_tagged_i8 (EsI8 as uint, v); } - fn emit_bool(v: bool) { self.wr_tagged_u8(EsBool as uint, v as u8) } + fn emit_bool(&self, v: bool) { + self.wr_tagged_u8(EsBool as uint, v as u8) + } // FIXME (#2742): implement these - fn emit_f64(_v: f64) { fail ~"Unimplemented: serializing an f64"; } - fn emit_f32(_v: f32) { fail ~"Unimplemented: serializing an f32"; } - fn emit_float(_v: float) { fail ~"Unimplemented: serializing a float"; } + fn emit_f64(&self, _v: f64) { fail ~"Unimplemented: serializing an f64"; } + fn emit_f32(&self, _v: f32) { fail ~"Unimplemented: serializing an f32"; } + fn emit_float(&self, _v: float) { + fail ~"Unimplemented: serializing a float"; + } - fn emit_str(v: &str) { self.wr_tagged_str(EsStr as uint, v) } + fn emit_char(&self, _v: char) { + fail ~"Unimplemented: serializing a char"; + } - fn emit_enum(name: &str, f: fn()) { + fn emit_borrowed_str(&self, v: &str) { + self.wr_tagged_str(EsStr as uint, v) + } + + fn emit_owned_str(&self, v: &str) { + self.emit_borrowed_str(v) + } + + fn emit_managed_str(&self, v: &str) { + self.emit_borrowed_str(v) + } + + fn emit_borrowed(&self, f: fn()) { f() } + fn emit_owned(&self, f: fn()) { f() } + fn emit_managed(&self, f: fn()) { f() } + + fn emit_enum(&self, name: &str, f: fn()) { self._emit_label(name); self.wr_tag(EsEnum as uint, f) } - fn emit_enum_variant(_v_name: &str, v_id: uint, _cnt: uint, f: fn()) { + fn emit_enum_variant(&self, _v_name: &str, v_id: uint, _cnt: uint, + f: fn()) { self._emit_tagged_uint(EsEnumVid, v_id); self.wr_tag(EsEnumBody as uint, f) } - fn emit_enum_variant_arg(_idx: uint, f: fn()) { f() } + fn emit_enum_variant_arg(&self, _idx: uint, f: fn()) { f() } - fn emit_vec(len: uint, f: fn()) { + fn emit_borrowed_vec(&self, len: uint, f: fn()) { do self.wr_tag(EsVec as uint) { self._emit_tagged_uint(EsVecLen, len); f() } } - fn emit_vec_elt(_idx: uint, f: fn()) { + fn emit_owned_vec(&self, len: uint, f: fn()) { + self.emit_borrowed_vec(len, f) + } + + fn emit_managed_vec(&self, len: uint, f: fn()) { + self.emit_borrowed_vec(len, f) + } + + fn emit_vec_elt(&self, _idx: uint, f: fn()) { self.wr_tag(EsVecElt as uint, f) } - fn emit_box(f: fn()) { f() } - fn emit_uniq(f: fn()) { f() } - fn emit_rec(f: fn()) { f() } - fn emit_rec_field(f_name: &str, _f_idx: uint, f: fn()) { - self._emit_label(f_name); + fn emit_rec(&self, f: fn()) { f() } + fn emit_struct(&self, _name: &str, f: fn()) { f() } + fn emit_field(&self, name: &str, _idx: uint, f: fn()) { + self._emit_label(name); f() } - fn emit_tup(_sz: uint, f: fn()) { f() } - fn emit_tup_elt(_idx: uint, f: fn()) { f() } + + fn emit_tup(&self, _len: uint, f: fn()) { f() } + fn emit_tup_elt(&self, _idx: uint, f: fn()) { f() } } -type EbmlDeserializer_ = {mut parent: ebml::Doc, - mut pos: uint}; - -pub enum EbmlDeserializer { - EbmlDeserializer_(EbmlDeserializer_) +struct Deserializer { + priv mut parent: Doc, + priv mut pos: uint, } -pub fn ebml_deserializer(d: ebml::Doc) -> EbmlDeserializer { - EbmlDeserializer_({mut parent: d, mut pos: d.start}) +pub fn Deserializer(d: Doc) -> Deserializer { + Deserializer { mut parent: d, mut pos: d.start } } -priv impl EbmlDeserializer { +priv impl Deserializer { fn _check_label(lbl: &str) { if self.pos < self.parent.end { - let {tag: r_tag, doc: r_doc} = - ebml::doc_at(self.parent.data, self.pos); + let TaggedDoc { tag: r_tag, doc: r_doc } = + doc_at(self.parent.data, self.pos); + if r_tag == (EsLabel as uint) { self.pos = r_doc.end; - let str = ebml::doc_as_str(r_doc); + let str = doc_as_str(r_doc); if lbl != str { fail fmt!("Expected label %s but found %s", lbl, str); } @@ -408,13 +450,13 @@ priv impl EbmlDeserializer { } } - fn next_doc(exp_tag: EbmlSerializerTag) -> ebml::Doc { + fn next_doc(exp_tag: EbmlSerializerTag) -> Doc { debug!(". next_doc(exp_tag=%?)", exp_tag); if self.pos >= self.parent.end { fail ~"no more documents in current node!"; } - let {tag: r_tag, doc: r_doc} = - ebml::doc_at(self.parent.data, self.pos); + let TaggedDoc { tag: r_tag, doc: r_doc } = + doc_at(self.parent.data, self.pos); debug!("self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?", copy self.parent.start, copy self.parent.end, copy self.pos, r_tag, r_doc.start, r_doc.end); @@ -427,10 +469,10 @@ priv impl EbmlDeserializer { r_doc.end, self.parent.end); } self.pos = r_doc.end; - return r_doc; + r_doc } - fn push_doc(d: ebml::Doc, f: fn() -> T) -> T{ + fn push_doc(d: Doc, f: fn() -> T) -> T{ let old_parent = self.parent; let old_pos = self.pos; self.parent = d; @@ -442,63 +484,76 @@ priv impl EbmlDeserializer { } fn _next_uint(exp_tag: EbmlSerializerTag) -> uint { - let r = ebml::doc_as_u32(self.next_doc(exp_tag)); + let r = doc_as_u32(self.next_doc(exp_tag)); debug!("_next_uint exp_tag=%? result=%?", exp_tag, r); - return r as uint; + r as uint } } -impl EbmlDeserializer { - fn read_opaque(op: fn(ebml::Doc) -> R) -> R { +impl Deserializer { + fn read_opaque(&self, op: fn(Doc) -> R) -> R { do self.push_doc(self.next_doc(EsOpaque)) { op(copy self.parent) } } } -impl EbmlDeserializer: serialization::Deserializer { - fn read_nil() -> () { () } +impl Deserializer: serialization::Deserializer { + fn read_nil(&self) -> () { () } - fn read_u64() -> u64 { ebml::doc_as_u64(self.next_doc(EsU64)) } - fn read_u32() -> u32 { ebml::doc_as_u32(self.next_doc(EsU32)) } - fn read_u16() -> u16 { ebml::doc_as_u16(self.next_doc(EsU16)) } - fn read_u8 () -> u8 { ebml::doc_as_u8 (self.next_doc(EsU8 )) } - fn read_uint() -> uint { - let v = ebml::doc_as_u64(self.next_doc(EsUint)); + fn read_u64(&self) -> u64 { doc_as_u64(self.next_doc(EsU64)) } + fn read_u32(&self) -> u32 { doc_as_u32(self.next_doc(EsU32)) } + fn read_u16(&self) -> u16 { doc_as_u16(self.next_doc(EsU16)) } + fn read_u8 (&self) -> u8 { doc_as_u8 (self.next_doc(EsU8 )) } + fn read_uint(&self) -> uint { + let v = doc_as_u64(self.next_doc(EsUint)); if v > (core::uint::max_value as u64) { fail fmt!("uint %? too large for this architecture", v); } - return v as uint; + v as uint } - fn read_i64() -> i64 { ebml::doc_as_u64(self.next_doc(EsI64)) as i64 } - fn read_i32() -> i32 { ebml::doc_as_u32(self.next_doc(EsI32)) as i32 } - fn read_i16() -> i16 { ebml::doc_as_u16(self.next_doc(EsI16)) as i16 } - fn read_i8 () -> i8 { ebml::doc_as_u8 (self.next_doc(EsI8 )) as i8 } - fn read_int() -> int { - let v = ebml::doc_as_u64(self.next_doc(EsInt)) as i64; + fn read_i64(&self) -> i64 { doc_as_u64(self.next_doc(EsI64)) as i64 } + fn read_i32(&self) -> i32 { doc_as_u32(self.next_doc(EsI32)) as i32 } + fn read_i16(&self) -> i16 { doc_as_u16(self.next_doc(EsI16)) as i16 } + fn read_i8 (&self) -> i8 { doc_as_u8 (self.next_doc(EsI8 )) as i8 } + fn read_int(&self) -> int { + let v = doc_as_u64(self.next_doc(EsInt)) as i64; if v > (int::max_value as i64) || v < (int::min_value as i64) { fail fmt!("int %? out of range for this architecture", v); } - return v as int; + v as int } - fn read_bool() -> bool { ebml::doc_as_u8(self.next_doc(EsBool)) as bool } + fn read_bool(&self) -> bool { doc_as_u8(self.next_doc(EsBool)) as bool } - fn read_f64() -> f64 { fail ~"read_f64()"; } - fn read_f32() -> f32 { fail ~"read_f32()"; } - fn read_float() -> float { fail ~"read_float()"; } + fn read_f64(&self) -> f64 { fail ~"read_f64()"; } + fn read_f32(&self) -> f32 { fail ~"read_f32()"; } + fn read_float(&self) -> float { fail ~"read_float()"; } - fn read_str() -> ~str { ebml::doc_as_str(self.next_doc(EsStr)) } + fn read_char(&self) -> char { fail ~"read_char()"; } + + fn read_owned_str(&self) -> ~str { doc_as_str(self.next_doc(EsStr)) } + fn read_managed_str(&self) -> @str { fail ~"read_managed_str()"; } // Compound types: - fn read_enum(name: &str, f: fn() -> T) -> T { + fn read_owned(&self, f: fn() -> T) -> T { + debug!("read_owned()"); + f() + } + + fn read_managed(&self, f: fn() -> T) -> T { + debug!("read_managed()"); + f() + } + + fn read_enum(&self, name: &str, f: fn() -> T) -> T { debug!("read_enum(%s)", name); self._check_label(name); self.push_doc(self.next_doc(EsEnum), f) } - fn read_enum_variant(f: fn(uint) -> T) -> T { + fn read_enum_variant(&self, f: fn(uint) -> T) -> T { debug!("read_enum_variant()"); let idx = self._next_uint(EsEnumVid); debug!(" idx=%u", idx); @@ -507,13 +562,13 @@ impl EbmlDeserializer: serialization::Deserializer { } } - fn read_enum_variant_arg(idx: uint, f: fn() -> T) -> T { + fn read_enum_variant_arg(&self, idx: uint, f: fn() -> T) -> T { debug!("read_enum_variant_arg(idx=%u)", idx); f() } - fn read_vec(f: fn(uint) -> T) -> T { - debug!("read_vec()"); + fn read_owned_vec(&self, f: fn(uint) -> T) -> T { + debug!("read_owned_vec()"); do self.push_doc(self.next_doc(EsVec)) { let len = self._next_uint(EsVecLen); debug!(" len=%u", len); @@ -521,104 +576,69 @@ impl EbmlDeserializer: serialization::Deserializer { } } - fn read_vec_elt(idx: uint, f: fn() -> T) -> T { + fn read_managed_vec(&self, f: fn(uint) -> T) -> T { + debug!("read_managed_vec()"); + do self.push_doc(self.next_doc(EsVec)) { + let len = self._next_uint(EsVecLen); + debug!(" len=%u", len); + f(len) + } + } + + fn read_vec_elt(&self, idx: uint, f: fn() -> T) -> T { debug!("read_vec_elt(idx=%u)", idx); self.push_doc(self.next_doc(EsVecElt), f) } - fn read_box(f: fn() -> T) -> T { - debug!("read_box()"); - f() - } - - fn read_uniq(f: fn() -> T) -> T { - debug!("read_uniq()"); - f() - } - - fn read_rec(f: fn() -> T) -> T { + fn read_rec(&self, f: fn() -> T) -> T { debug!("read_rec()"); f() } - fn read_rec_field(f_name: &str, f_idx: uint, f: fn() -> T) -> T { - debug!("read_rec_field(%s, idx=%u)", f_name, f_idx); - self._check_label(f_name); + fn read_struct(&self, name: &str, f: fn() -> T) -> T { + debug!("read_struct(name=%s)", name); f() } - fn read_tup(sz: uint, f: fn() -> T) -> T { - debug!("read_tup(sz=%u)", sz); + fn read_field(&self, name: &str, idx: uint, f: fn() -> T) -> T { + debug!("read_field(name=%s, idx=%u)", name, idx); + self._check_label(name); f() } - fn read_tup_elt(idx: uint, f: fn() -> T) -> T { + fn read_tup(&self, len: uint, f: fn() -> T) -> T { + debug!("read_tup(len=%u)", len); + f() + } + + fn read_tup_elt(&self, idx: uint, f: fn() -> T) -> T { debug!("read_tup_elt(idx=%u)", idx); f() } } - // ___________________________________________________________________________ // Testing -#[test] -fn test_option_int() { - fn serialize_1(s: &S, v: int) { - s.emit_i64(v as i64); - } - - fn serialize_0(s: &S, v: Option) { - do s.emit_enum(~"core::option::t") { - match v { - None => s.emit_enum_variant( - ~"core::option::None", 0u, 0u, || { } ), - Some(v0) => { - do s.emit_enum_variant(~"core::option::some", 1u, 1u) { - s.emit_enum_variant_arg(0u, || serialize_1(s, v0)); - } - } - } +#[cfg(test)] +mod tests { + #[test] + fn test_option_int() { + fn test_v(v: Option) { + debug!("v == %?", v); + let bytes = do io::with_bytes_writer |wr| { + let ebml_w = Serializer(wr); + v.serialize(&ebml_w) + }; + let ebml_doc = Doc(@bytes); + let deser = Deserializer(ebml_doc); + let v1 = serialization::deserialize(&deser); + debug!("v1 == %?", v1); + assert v == v1; } - } - fn deserialize_1(s: &S) -> int { - s.read_i64() as int + test_v(Some(22)); + test_v(None); + test_v(Some(3)); } - - fn deserialize_0(s: &S) -> Option { - do s.read_enum(~"core::option::t") { - do s.read_enum_variant |i| { - match i { - 0 => None, - 1 => { - let v0 = do s.read_enum_variant_arg(0u) { - deserialize_1(s) - }; - Some(v0) - } - _ => { - fail #fmt("deserialize_0: unexpected variant %u", i); - } - } - } - } - } - - fn test_v(v: Option) { - debug!("v == %?", v); - let bytes = do io::with_bytes_writer |wr| { - let ebml_w = ebml::Writer(wr); - serialize_0(&ebml_w, v); - }; - let ebml_doc = ebml::Doc(@bytes); - let deser = ebml_deserializer(ebml_doc); - let v1 = deserialize_0(&deser); - debug!("v1 == %?", v1); - assert v == v1; - } - - test_v(Some(22)); - test_v(None); - test_v(Some(3)); } diff --git a/src/libstd/ebml2.rs b/src/libstd/ebml2.rs index f88aad1ac633..f5410233c921 100644 --- a/src/libstd/ebml2.rs +++ b/src/libstd/ebml2.rs @@ -1,644 +1 @@ -#[forbid(deprecated_mode)]; -use serialization2; - -// Simple Extensible Binary Markup Language (ebml) reader and writer on a -// cursor model. See the specification here: -// http://www.matroska.org/technical/specs/rfc/index.html - -struct EbmlTag { - id: uint, - size: uint, -} - -struct EbmlState { - ebml_tag: EbmlTag, - tag_pos: uint, - data_pos: uint, -} - -// FIXME (#2739): When we have module renaming, make "reader" and "writer" -// separate modules within this file. - -// ebml reading -struct Doc { - data: @~[u8], - start: uint, - end: uint, -} - -struct TaggedDoc { - tag: uint, - doc: Doc, -} - -impl Doc: ops::Index { - pure fn index(tag: uint) -> Doc { - unsafe { - get_doc(self, tag) - } - } -} - -fn vuint_at(data: &[u8], start: uint) -> {val: uint, next: uint} { - let a = data[start]; - if a & 0x80u8 != 0u8 { - return {val: (a & 0x7fu8) as uint, next: start + 1u}; - } - if a & 0x40u8 != 0u8 { - return {val: ((a & 0x3fu8) as uint) << 8u | - (data[start + 1u] as uint), - next: start + 2u}; - } else if a & 0x20u8 != 0u8 { - return {val: ((a & 0x1fu8) as uint) << 16u | - (data[start + 1u] as uint) << 8u | - (data[start + 2u] as uint), - next: start + 3u}; - } else if a & 0x10u8 != 0u8 { - return {val: ((a & 0x0fu8) as uint) << 24u | - (data[start + 1u] as uint) << 16u | - (data[start + 2u] as uint) << 8u | - (data[start + 3u] as uint), - next: start + 4u}; - } else { error!("vint too big"); fail; } -} - -pub fn Doc(data: @~[u8]) -> Doc { - Doc { data: data, start: 0u, end: vec::len::(*data) } -} - -pub fn doc_at(data: @~[u8], start: uint) -> TaggedDoc { - let elt_tag = vuint_at(*data, start); - let elt_size = vuint_at(*data, elt_tag.next); - let end = elt_size.next + elt_size.val; - TaggedDoc { - tag: elt_tag.val, - doc: Doc { data: data, start: elt_size.next, end: end } - } -} - -pub fn maybe_get_doc(d: Doc, tg: uint) -> Option { - let mut pos = d.start; - while pos < d.end { - let elt_tag = vuint_at(*d.data, pos); - let elt_size = vuint_at(*d.data, elt_tag.next); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tg { - return Some(Doc { data: d.data, start: elt_size.next, end: pos }); - } - } - None -} - -pub fn get_doc(d: Doc, tg: uint) -> Doc { - match maybe_get_doc(d, tg) { - Some(d) => d, - None => { - error!("failed to find block with tag %u", tg); - fail; - } - } -} - -pub fn docs(d: Doc, it: fn(uint, Doc) -> bool) { - let mut pos = d.start; - while pos < d.end { - let elt_tag = vuint_at(*d.data, pos); - let elt_size = vuint_at(*d.data, elt_tag.next); - pos = elt_size.next + elt_size.val; - let doc = Doc { data: d.data, start: elt_size.next, end: pos }; - if !it(elt_tag.val, doc) { - break; - } - } -} - -pub fn tagged_docs(d: Doc, tg: uint, it: fn(Doc) -> bool) { - let mut pos = d.start; - while pos < d.end { - let elt_tag = vuint_at(*d.data, pos); - let elt_size = vuint_at(*d.data, elt_tag.next); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tg { - let doc = Doc { data: d.data, start: elt_size.next, end: pos }; - if !it(doc) { - break; - } - } - } -} - -pub fn doc_data(d: Doc) -> ~[u8] { vec::slice::(*d.data, d.start, d.end) } - -pub fn with_doc_data(d: Doc, f: fn(x: &[u8]) -> T) -> T { - f(vec::view(*d.data, d.start, d.end)) -} - -pub fn doc_as_str(d: Doc) -> ~str { str::from_bytes(doc_data(d)) } - -pub fn doc_as_u8(d: Doc) -> u8 { - assert d.end == d.start + 1u; - (*d.data)[d.start] -} - -pub fn doc_as_u16(d: Doc) -> u16 { - assert d.end == d.start + 2u; - io::u64_from_be_bytes(*d.data, d.start, 2u) as u16 -} - -pub fn doc_as_u32(d: Doc) -> u32 { - assert d.end == d.start + 4u; - io::u64_from_be_bytes(*d.data, d.start, 4u) as u32 -} - -pub fn doc_as_u64(d: Doc) -> u64 { - assert d.end == d.start + 8u; - io::u64_from_be_bytes(*d.data, d.start, 8u) -} - -pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 } -pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 } -pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 } -pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 } - -// ebml writing -struct Serializer { - writer: io::Writer, - priv mut size_positions: ~[uint], -} - -fn write_sized_vuint(w: io::Writer, n: uint, size: uint) { - match size { - 1u => w.write(&[0x80u8 | (n as u8)]), - 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]), - 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8, - n as u8]), - 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8, - (n >> 8_u) as u8, n as u8]), - _ => fail fmt!("vint to write too big: %?", n) - }; -} - -fn write_vuint(w: io::Writer, n: uint) { - if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; } - if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; } - if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; } - if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; } - fail fmt!("vint to write too big: %?", n); -} - -pub fn Serializer(w: io::Writer) -> Serializer { - let size_positions: ~[uint] = ~[]; - Serializer { writer: w, mut size_positions: size_positions } -} - -// FIXME (#2741): Provide a function to write the standard ebml header. -impl Serializer { - fn start_tag(tag_id: uint) { - debug!("Start tag %u", tag_id); - - // Write the enum ID: - write_vuint(self.writer, tag_id); - - // Write a placeholder four-byte size. - self.size_positions.push(self.writer.tell()); - let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8]; - self.writer.write(zeroes); - } - - fn end_tag() { - let last_size_pos = self.size_positions.pop(); - let cur_pos = self.writer.tell(); - self.writer.seek(last_size_pos as int, io::SeekSet); - let size = (cur_pos - last_size_pos - 4u); - write_sized_vuint(self.writer, size, 4u); - self.writer.seek(cur_pos as int, io::SeekSet); - - debug!("End tag (size = %u)", size); - } - - fn wr_tag(tag_id: uint, blk: fn()) { - self.start_tag(tag_id); - blk(); - self.end_tag(); - } - - fn wr_tagged_bytes(tag_id: uint, b: &[u8]) { - write_vuint(self.writer, tag_id); - write_vuint(self.writer, vec::len(b)); - self.writer.write(b); - } - - fn wr_tagged_u64(tag_id: uint, v: u64) { - do io::u64_to_be_bytes(v, 8u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_u32(tag_id: uint, v: u32) { - do io::u64_to_be_bytes(v as u64, 4u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_u16(tag_id: uint, v: u16) { - do io::u64_to_be_bytes(v as u64, 2u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_u8(tag_id: uint, v: u8) { - self.wr_tagged_bytes(tag_id, &[v]); - } - - fn wr_tagged_i64(tag_id: uint, v: i64) { - do io::u64_to_be_bytes(v as u64, 8u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_i32(tag_id: uint, v: i32) { - do io::u64_to_be_bytes(v as u64, 4u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_i16(tag_id: uint, v: i16) { - do io::u64_to_be_bytes(v as u64, 2u) |v| { - self.wr_tagged_bytes(tag_id, v); - } - } - - fn wr_tagged_i8(tag_id: uint, v: i8) { - self.wr_tagged_bytes(tag_id, &[v as u8]); - } - - fn wr_tagged_str(tag_id: uint, v: &str) { - str::byte_slice(v, |b| self.wr_tagged_bytes(tag_id, b)); - } - - fn wr_bytes(b: &[u8]) { - debug!("Write %u bytes", vec::len(b)); - self.writer.write(b); - } - - fn wr_str(s: &str) { - debug!("Write str: %?", s); - self.writer.write(str::to_bytes(s)); - } -} - -// FIXME (#2743): optionally perform "relaxations" on end_tag to more -// efficiently encode sizes; this is a fixed point iteration - -// Set to true to generate more debugging in EBML serialization. -// Totally lame approach. -const debug: bool = false; - -enum EbmlSerializerTag { - EsUint, EsU64, EsU32, EsU16, EsU8, - EsInt, EsI64, EsI32, EsI16, EsI8, - EsBool, - EsStr, - EsF64, EsF32, EsFloat, - EsEnum, EsEnumVid, EsEnumBody, - EsVec, EsVecLen, EsVecElt, - - EsOpaque, - - EsLabel // Used only when debugging -} - -priv impl Serializer { - // used internally to emit things like the vector length and so on - fn _emit_tagged_uint(t: EbmlSerializerTag, v: uint) { - assert v <= 0xFFFF_FFFF_u; - self.wr_tagged_u32(t as uint, v as u32); - } - - fn _emit_label(label: &str) { - // There are various strings that we have access to, such as - // the name of a record field, which do not actually appear in - // the serialized EBML (normally). This is just for - // efficiency. When debugging, though, we can emit such - // labels and then they will be checked by deserializer to - // try and check failures more quickly. - if debug { self.wr_tagged_str(EsLabel as uint, label) } - } -} - -impl Serializer { - fn emit_opaque(&self, f: fn()) { - do self.wr_tag(EsOpaque as uint) { - f() - } - } -} - -impl Serializer: serialization2::Serializer { - fn emit_nil(&self) {} - - fn emit_uint(&self, v: uint) { - self.wr_tagged_u64(EsUint as uint, v as u64); - } - fn emit_u64(&self, v: u64) { self.wr_tagged_u64(EsU64 as uint, v); } - fn emit_u32(&self, v: u32) { self.wr_tagged_u32(EsU32 as uint, v); } - fn emit_u16(&self, v: u16) { self.wr_tagged_u16(EsU16 as uint, v); } - fn emit_u8(&self, v: u8) { self.wr_tagged_u8 (EsU8 as uint, v); } - - fn emit_int(&self, v: int) { - self.wr_tagged_i64(EsInt as uint, v as i64); - } - fn emit_i64(&self, v: i64) { self.wr_tagged_i64(EsI64 as uint, v); } - fn emit_i32(&self, v: i32) { self.wr_tagged_i32(EsI32 as uint, v); } - fn emit_i16(&self, v: i16) { self.wr_tagged_i16(EsI16 as uint, v); } - fn emit_i8(&self, v: i8) { self.wr_tagged_i8 (EsI8 as uint, v); } - - fn emit_bool(&self, v: bool) { - self.wr_tagged_u8(EsBool as uint, v as u8) - } - - // FIXME (#2742): implement these - fn emit_f64(&self, _v: f64) { fail ~"Unimplemented: serializing an f64"; } - fn emit_f32(&self, _v: f32) { fail ~"Unimplemented: serializing an f32"; } - fn emit_float(&self, _v: float) { - fail ~"Unimplemented: serializing a float"; - } - - fn emit_char(&self, _v: char) { - fail ~"Unimplemented: serializing a char"; - } - - fn emit_borrowed_str(&self, v: &str) { - self.wr_tagged_str(EsStr as uint, v) - } - - fn emit_owned_str(&self, v: &str) { - self.emit_borrowed_str(v) - } - - fn emit_managed_str(&self, v: &str) { - self.emit_borrowed_str(v) - } - - fn emit_borrowed(&self, f: fn()) { f() } - fn emit_owned(&self, f: fn()) { f() } - fn emit_managed(&self, f: fn()) { f() } - - fn emit_enum(&self, name: &str, f: fn()) { - self._emit_label(name); - self.wr_tag(EsEnum as uint, f) - } - fn emit_enum_variant(&self, _v_name: &str, v_id: uint, _cnt: uint, - f: fn()) { - self._emit_tagged_uint(EsEnumVid, v_id); - self.wr_tag(EsEnumBody as uint, f) - } - fn emit_enum_variant_arg(&self, _idx: uint, f: fn()) { f() } - - fn emit_borrowed_vec(&self, len: uint, f: fn()) { - do self.wr_tag(EsVec as uint) { - self._emit_tagged_uint(EsVecLen, len); - f() - } - } - - fn emit_owned_vec(&self, len: uint, f: fn()) { - self.emit_borrowed_vec(len, f) - } - - fn emit_managed_vec(&self, len: uint, f: fn()) { - self.emit_borrowed_vec(len, f) - } - - fn emit_vec_elt(&self, _idx: uint, f: fn()) { - self.wr_tag(EsVecElt as uint, f) - } - - fn emit_rec(&self, f: fn()) { f() } - fn emit_struct(&self, _name: &str, f: fn()) { f() } - fn emit_field(&self, name: &str, _idx: uint, f: fn()) { - self._emit_label(name); - f() - } - - fn emit_tup(&self, _len: uint, f: fn()) { f() } - fn emit_tup_elt(&self, _idx: uint, f: fn()) { f() } -} - -struct Deserializer { - priv mut parent: Doc, - priv mut pos: uint, -} - -pub fn Deserializer(d: Doc) -> Deserializer { - Deserializer { mut parent: d, mut pos: d.start } -} - -priv impl Deserializer { - fn _check_label(lbl: &str) { - if self.pos < self.parent.end { - let TaggedDoc { tag: r_tag, doc: r_doc } = - doc_at(self.parent.data, self.pos); - - if r_tag == (EsLabel as uint) { - self.pos = r_doc.end; - let str = doc_as_str(r_doc); - if lbl != str { - fail fmt!("Expected label %s but found %s", lbl, str); - } - } - } - } - - fn next_doc(exp_tag: EbmlSerializerTag) -> Doc { - debug!(". next_doc(exp_tag=%?)", exp_tag); - if self.pos >= self.parent.end { - fail ~"no more documents in current node!"; - } - let TaggedDoc { tag: r_tag, doc: r_doc } = - doc_at(self.parent.data, self.pos); - debug!("self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?", - copy self.parent.start, copy self.parent.end, - copy self.pos, r_tag, r_doc.start, r_doc.end); - if r_tag != (exp_tag as uint) { - fail fmt!("expected EMBL doc with tag %? but found tag %?", - exp_tag, r_tag); - } - if r_doc.end > self.parent.end { - fail fmt!("invalid EBML, child extends to 0x%x, parent to 0x%x", - r_doc.end, self.parent.end); - } - self.pos = r_doc.end; - r_doc - } - - fn push_doc(d: Doc, f: fn() -> T) -> T{ - let old_parent = self.parent; - let old_pos = self.pos; - self.parent = d; - self.pos = d.start; - let r = f(); - self.parent = old_parent; - self.pos = old_pos; - move r - } - - fn _next_uint(exp_tag: EbmlSerializerTag) -> uint { - let r = doc_as_u32(self.next_doc(exp_tag)); - debug!("_next_uint exp_tag=%? result=%?", exp_tag, r); - r as uint - } -} - -impl Deserializer { - fn read_opaque(&self, op: fn(Doc) -> R) -> R { - do self.push_doc(self.next_doc(EsOpaque)) { - op(copy self.parent) - } - } -} - -impl Deserializer: serialization2::Deserializer { - fn read_nil(&self) -> () { () } - - fn read_u64(&self) -> u64 { doc_as_u64(self.next_doc(EsU64)) } - fn read_u32(&self) -> u32 { doc_as_u32(self.next_doc(EsU32)) } - fn read_u16(&self) -> u16 { doc_as_u16(self.next_doc(EsU16)) } - fn read_u8 (&self) -> u8 { doc_as_u8 (self.next_doc(EsU8 )) } - fn read_uint(&self) -> uint { - let v = doc_as_u64(self.next_doc(EsUint)); - if v > (core::uint::max_value as u64) { - fail fmt!("uint %? too large for this architecture", v); - } - v as uint - } - - fn read_i64(&self) -> i64 { doc_as_u64(self.next_doc(EsI64)) as i64 } - fn read_i32(&self) -> i32 { doc_as_u32(self.next_doc(EsI32)) as i32 } - fn read_i16(&self) -> i16 { doc_as_u16(self.next_doc(EsI16)) as i16 } - fn read_i8 (&self) -> i8 { doc_as_u8 (self.next_doc(EsI8 )) as i8 } - fn read_int(&self) -> int { - let v = doc_as_u64(self.next_doc(EsInt)) as i64; - if v > (int::max_value as i64) || v < (int::min_value as i64) { - fail fmt!("int %? out of range for this architecture", v); - } - v as int - } - - fn read_bool(&self) -> bool { doc_as_u8(self.next_doc(EsBool)) as bool } - - fn read_f64(&self) -> f64 { fail ~"read_f64()"; } - fn read_f32(&self) -> f32 { fail ~"read_f32()"; } - fn read_float(&self) -> float { fail ~"read_float()"; } - - fn read_char(&self) -> char { fail ~"read_char()"; } - - fn read_owned_str(&self) -> ~str { doc_as_str(self.next_doc(EsStr)) } - fn read_managed_str(&self) -> @str { fail ~"read_managed_str()"; } - - // Compound types: - fn read_owned(&self, f: fn() -> T) -> T { - debug!("read_owned()"); - f() - } - - fn read_managed(&self, f: fn() -> T) -> T { - debug!("read_managed()"); - f() - } - - fn read_enum(&self, name: &str, f: fn() -> T) -> T { - debug!("read_enum(%s)", name); - self._check_label(name); - self.push_doc(self.next_doc(EsEnum), f) - } - - fn read_enum_variant(&self, f: fn(uint) -> T) -> T { - debug!("read_enum_variant()"); - let idx = self._next_uint(EsEnumVid); - debug!(" idx=%u", idx); - do self.push_doc(self.next_doc(EsEnumBody)) { - f(idx) - } - } - - fn read_enum_variant_arg(&self, idx: uint, f: fn() -> T) -> T { - debug!("read_enum_variant_arg(idx=%u)", idx); - f() - } - - fn read_owned_vec(&self, f: fn(uint) -> T) -> T { - debug!("read_owned_vec()"); - do self.push_doc(self.next_doc(EsVec)) { - let len = self._next_uint(EsVecLen); - debug!(" len=%u", len); - f(len) - } - } - - fn read_managed_vec(&self, f: fn(uint) -> T) -> T { - debug!("read_managed_vec()"); - do self.push_doc(self.next_doc(EsVec)) { - let len = self._next_uint(EsVecLen); - debug!(" len=%u", len); - f(len) - } - } - - fn read_vec_elt(&self, idx: uint, f: fn() -> T) -> T { - debug!("read_vec_elt(idx=%u)", idx); - self.push_doc(self.next_doc(EsVecElt), f) - } - - fn read_rec(&self, f: fn() -> T) -> T { - debug!("read_rec()"); - f() - } - - fn read_struct(&self, name: &str, f: fn() -> T) -> T { - debug!("read_struct(name=%s)", name); - f() - } - - fn read_field(&self, name: &str, idx: uint, f: fn() -> T) -> T { - debug!("read_field(name=%s, idx=%u)", name, idx); - self._check_label(name); - f() - } - - fn read_tup(&self, len: uint, f: fn() -> T) -> T { - debug!("read_tup(len=%u)", len); - f() - } - - fn read_tup_elt(&self, idx: uint, f: fn() -> T) -> T { - debug!("read_tup_elt(idx=%u)", idx); - f() - } -} - -// ___________________________________________________________________________ -// Testing - -#[cfg(test)] -mod tests { - #[test] - fn test_option_int() { - fn test_v(v: Option) { - debug!("v == %?", v); - let bytes = do io::with_bytes_writer |wr| { - let ebml_w = Serializer(wr); - v.serialize(&ebml_w) - }; - let ebml_doc = Doc(@bytes); - let deser = Deserializer(ebml_doc); - let v1 = serialization2::deserialize(&deser); - debug!("v1 == %?", v1); - assert v == v1; - } - - test_v(Some(22)); - test_v(None); - test_v(Some(3)); - } -} +pub use ebml::*; diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 09d002162093..fa7c0286dc1e 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -63,7 +63,7 @@ pub fn Serializer(wr: io::Writer) -> Serializer { Serializer { wr: wr } } -pub impl Serializer: serialization2::Serializer { +pub impl Serializer: serialization::Serializer { fn emit_nil(&self) { self.wr.write_str("null") } fn emit_uint(&self, v: uint) { self.emit_float(v as float); } @@ -167,7 +167,7 @@ pub fn PrettySerializer(wr: io::Writer) -> PrettySerializer { PrettySerializer { wr: wr, indent: 0 } } -pub impl PrettySerializer: serialization2::Serializer { +pub impl PrettySerializer: serialization::Serializer { fn emit_nil(&self) { self.wr.write_str("null") } fn emit_uint(&self, v: uint) { self.emit_float(v as float); } @@ -273,8 +273,8 @@ pub impl PrettySerializer: serialization2::Serializer { } } -pub impl Json: serialization2::Serializable { - fn serialize(&self, s: &S) { +pub impl Json: serialization::Serializable { + fn serialize(&self, s: &S) { match *self { Number(v) => v.serialize(s), String(ref v) => v.serialize(s), @@ -721,7 +721,7 @@ priv impl Deserializer { } } -pub impl Deserializer: serialization2::Deserializer { +pub impl Deserializer: serialization::Deserializer { fn read_nil(&self) -> () { debug!("read_nil"); match *self.pop() { diff --git a/src/libstd/prettyprint.rs b/src/libstd/prettyprint.rs index bc528800666d..6119c03cdcaf 100644 --- a/src/libstd/prettyprint.rs +++ b/src/libstd/prettyprint.rs @@ -2,131 +2,175 @@ use io::Writer; use io::WriterUtil; -use serialization::Serializer; +use serialization; -impl Writer: Serializer { - fn emit_nil() { - self.write_str(~"()") +pub struct Serializer { + wr: io::Writer, +} + +pub fn Serializer(wr: io::Writer) -> Serializer { + Serializer { wr: wr } +} + +pub impl Serializer: serialization::Serializer { + fn emit_nil(&self) { + self.wr.write_str(~"()") } - fn emit_uint(v: uint) { - self.write_str(fmt!("%?u", v)); + fn emit_uint(&self, v: uint) { + self.wr.write_str(fmt!("%?u", v)); } - fn emit_u64(v: u64) { - self.write_str(fmt!("%?_u64", v)); + fn emit_u64(&self, v: u64) { + self.wr.write_str(fmt!("%?_u64", v)); } - fn emit_u32(v: u32) { - self.write_str(fmt!("%?_u32", v)); + fn emit_u32(&self, v: u32) { + self.wr.write_str(fmt!("%?_u32", v)); } - fn emit_u16(v: u16) { - self.write_str(fmt!("%?_u16", v)); + fn emit_u16(&self, v: u16) { + self.wr.write_str(fmt!("%?_u16", v)); } - fn emit_u8(v: u8) { - self.write_str(fmt!("%?_u8", v)); + fn emit_u8(&self, v: u8) { + self.wr.write_str(fmt!("%?_u8", v)); } - fn emit_int(v: int) { - self.write_str(fmt!("%?", v)); + fn emit_int(&self, v: int) { + self.wr.write_str(fmt!("%?", v)); } - fn emit_i64(v: i64) { - self.write_str(fmt!("%?_i64", v)); + fn emit_i64(&self, v: i64) { + self.wr.write_str(fmt!("%?_i64", v)); } - fn emit_i32(v: i32) { - self.write_str(fmt!("%?_i32", v)); + fn emit_i32(&self, v: i32) { + self.wr.write_str(fmt!("%?_i32", v)); } - fn emit_i16(v: i16) { - self.write_str(fmt!("%?_i16", v)); + fn emit_i16(&self, v: i16) { + self.wr.write_str(fmt!("%?_i16", v)); } - fn emit_i8(v: i8) { - self.write_str(fmt!("%?_i8", v)); + fn emit_i8(&self, v: i8) { + self.wr.write_str(fmt!("%?_i8", v)); } - fn emit_bool(v: bool) { - self.write_str(fmt!("%b", v)); + fn emit_bool(&self, v: bool) { + self.wr.write_str(fmt!("%b", v)); } - fn emit_float(v: float) { - self.write_str(fmt!("%?_f", v)); + fn emit_float(&self, v: float) { + self.wr.write_str(fmt!("%?_f", v)); } - fn emit_f64(v: f64) { - self.write_str(fmt!("%?_f64", v)); + fn emit_f64(&self, v: f64) { + self.wr.write_str(fmt!("%?_f64", v)); } - fn emit_f32(v: f32) { - self.write_str(fmt!("%?_f32", v)); + fn emit_f32(&self, v: f32) { + self.wr.write_str(fmt!("%?_f32", v)); } - fn emit_str(v: &str) { - self.write_str(fmt!("%?", v)); + fn emit_char(&self, v: char) { + self.wr.write_str(fmt!("%?", v)); } - fn emit_enum(_name: &str, f: fn()) { + fn emit_borrowed_str(&self, v: &str) { + self.wr.write_str(fmt!("&%?", v)); + } + + fn emit_owned_str(&self, v: &str) { + self.wr.write_str(fmt!("~%?", v)); + } + + fn emit_managed_str(&self, v: &str) { + self.wr.write_str(fmt!("@%?", v)); + } + + fn emit_borrowed(&self, f: fn()) { + self.wr.write_str(~"&"); f(); } - fn emit_enum_variant(v_name: &str, _v_id: uint, sz: uint, f: fn()) { - self.write_str(v_name); - if sz > 0u { self.write_str(~"("); } - f(); - if sz > 0u { self.write_str(~")"); } - } - - fn emit_enum_variant_arg(idx: uint, f: fn()) { - if idx > 0u { self.write_str(~", "); } + fn emit_owned(&self, f: fn()) { + self.wr.write_str(~"~"); f(); } - fn emit_vec(_len: uint, f: fn()) { - self.write_str(~"["); - f(); - self.write_str(~"]"); - } - - fn emit_vec_elt(idx: uint, f: fn()) { - if idx > 0u { self.write_str(~", "); } + fn emit_managed(&self, f: fn()) { + self.wr.write_str(~"@"); f(); } - fn emit_box(f: fn()) { - self.write_str(~"@"); + fn emit_enum(&self, _name: &str, f: fn()) { f(); } - fn emit_uniq(f: fn()) { - self.write_str(~"~"); + fn emit_enum_variant(&self, v_name: &str, _v_id: uint, sz: uint, + f: fn()) { + self.wr.write_str(v_name); + if sz > 0u { self.wr.write_str(~"("); } + f(); + if sz > 0u { self.wr.write_str(~")"); } + } + + fn emit_enum_variant_arg(&self, idx: uint, f: fn()) { + if idx > 0u { self.wr.write_str(~", "); } f(); } - fn emit_rec(f: fn()) { - self.write_str(~"{"); + fn emit_borrowed_vec(&self, _len: uint, f: fn()) { + self.wr.write_str(~"&["); f(); - self.write_str(~"}"); + self.wr.write_str(~"]"); } - fn emit_rec_field(f_name: &str, f_idx: uint, f: fn()) { - if f_idx > 0u { self.write_str(~", "); } - self.write_str(f_name); - self.write_str(~": "); + fn emit_owned_vec(&self, _len: uint, f: fn()) { + self.wr.write_str(~"~["); + f(); + self.wr.write_str(~"]"); + } + + fn emit_managed_vec(&self, _len: uint, f: fn()) { + self.wr.write_str(~"@["); + f(); + self.wr.write_str(~"]"); + } + + fn emit_vec_elt(&self, idx: uint, f: fn()) { + if idx > 0u { self.wr.write_str(~", "); } f(); } - fn emit_tup(_sz: uint, f: fn()) { - self.write_str(~"("); + fn emit_rec(&self, f: fn()) { + self.wr.write_str(~"{"); f(); - self.write_str(~")"); + self.wr.write_str(~"}"); } - fn emit_tup_elt(idx: uint, f: fn()) { - if idx > 0u { self.write_str(~", "); } + fn emit_struct(&self, name: &str, f: fn()) { + self.wr.write_str(fmt!("%s {", name)); + f(); + self.wr.write_str(~"}"); + } + + fn emit_field(&self, name: &str, idx: uint, f: fn()) { + if idx > 0u { self.wr.write_str(~", "); } + self.wr.write_str(name); + self.wr.write_str(~": "); + f(); + } + + fn emit_tup(&self, _len: uint, f: fn()) { + self.wr.write_str(~"("); + f(); + self.wr.write_str(~")"); + } + + fn emit_tup_elt(&self, idx: uint, f: fn()) { + if idx > 0u { self.wr.write_str(~", "); } f(); } } diff --git a/src/libstd/prettyprint2.rs b/src/libstd/prettyprint2.rs index 87af519eb123..a3bf40ecf72f 100644 --- a/src/libstd/prettyprint2.rs +++ b/src/libstd/prettyprint2.rs @@ -1,176 +1 @@ -#[forbid(deprecated_mode)]; - -use io::Writer; -use io::WriterUtil; -use serialization2; - -pub struct Serializer { - wr: io::Writer, -} - -pub fn Serializer(wr: io::Writer) -> Serializer { - Serializer { wr: wr } -} - -pub impl Serializer: serialization2::Serializer { - fn emit_nil(&self) { - self.wr.write_str(~"()") - } - - fn emit_uint(&self, v: uint) { - self.wr.write_str(fmt!("%?u", v)); - } - - fn emit_u64(&self, v: u64) { - self.wr.write_str(fmt!("%?_u64", v)); - } - - fn emit_u32(&self, v: u32) { - self.wr.write_str(fmt!("%?_u32", v)); - } - - fn emit_u16(&self, v: u16) { - self.wr.write_str(fmt!("%?_u16", v)); - } - - fn emit_u8(&self, v: u8) { - self.wr.write_str(fmt!("%?_u8", v)); - } - - fn emit_int(&self, v: int) { - self.wr.write_str(fmt!("%?", v)); - } - - fn emit_i64(&self, v: i64) { - self.wr.write_str(fmt!("%?_i64", v)); - } - - fn emit_i32(&self, v: i32) { - self.wr.write_str(fmt!("%?_i32", v)); - } - - fn emit_i16(&self, v: i16) { - self.wr.write_str(fmt!("%?_i16", v)); - } - - fn emit_i8(&self, v: i8) { - self.wr.write_str(fmt!("%?_i8", v)); - } - - fn emit_bool(&self, v: bool) { - self.wr.write_str(fmt!("%b", v)); - } - - fn emit_float(&self, v: float) { - self.wr.write_str(fmt!("%?_f", v)); - } - - fn emit_f64(&self, v: f64) { - self.wr.write_str(fmt!("%?_f64", v)); - } - - fn emit_f32(&self, v: f32) { - self.wr.write_str(fmt!("%?_f32", v)); - } - - fn emit_char(&self, v: char) { - self.wr.write_str(fmt!("%?", v)); - } - - fn emit_borrowed_str(&self, v: &str) { - self.wr.write_str(fmt!("&%?", v)); - } - - fn emit_owned_str(&self, v: &str) { - self.wr.write_str(fmt!("~%?", v)); - } - - fn emit_managed_str(&self, v: &str) { - self.wr.write_str(fmt!("@%?", v)); - } - - fn emit_borrowed(&self, f: fn()) { - self.wr.write_str(~"&"); - f(); - } - - fn emit_owned(&self, f: fn()) { - self.wr.write_str(~"~"); - f(); - } - - fn emit_managed(&self, f: fn()) { - self.wr.write_str(~"@"); - f(); - } - - fn emit_enum(&self, _name: &str, f: fn()) { - f(); - } - - fn emit_enum_variant(&self, v_name: &str, _v_id: uint, sz: uint, - f: fn()) { - self.wr.write_str(v_name); - if sz > 0u { self.wr.write_str(~"("); } - f(); - if sz > 0u { self.wr.write_str(~")"); } - } - - fn emit_enum_variant_arg(&self, idx: uint, f: fn()) { - if idx > 0u { self.wr.write_str(~", "); } - f(); - } - - fn emit_borrowed_vec(&self, _len: uint, f: fn()) { - self.wr.write_str(~"&["); - f(); - self.wr.write_str(~"]"); - } - - fn emit_owned_vec(&self, _len: uint, f: fn()) { - self.wr.write_str(~"~["); - f(); - self.wr.write_str(~"]"); - } - - fn emit_managed_vec(&self, _len: uint, f: fn()) { - self.wr.write_str(~"@["); - f(); - self.wr.write_str(~"]"); - } - - fn emit_vec_elt(&self, idx: uint, f: fn()) { - if idx > 0u { self.wr.write_str(~", "); } - f(); - } - - fn emit_rec(&self, f: fn()) { - self.wr.write_str(~"{"); - f(); - self.wr.write_str(~"}"); - } - - fn emit_struct(&self, name: &str, f: fn()) { - self.wr.write_str(fmt!("%s {", name)); - f(); - self.wr.write_str(~"}"); - } - - fn emit_field(&self, name: &str, idx: uint, f: fn()) { - if idx > 0u { self.wr.write_str(~", "); } - self.wr.write_str(name); - self.wr.write_str(~": "); - f(); - } - - fn emit_tup(&self, _len: uint, f: fn()) { - self.wr.write_str(~"("); - f(); - self.wr.write_str(~")"); - } - - fn emit_tup_elt(&self, idx: uint, f: fn()) { - if idx > 0u { self.wr.write_str(~", "); } - f(); - } -} +pub use prettyprint::*; diff --git a/src/libstd/serialization.rs b/src/libstd/serialization.rs index 8ba00e65dec9..5173ef163a22 100644 --- a/src/libstd/serialization.rs +++ b/src/libstd/serialization.rs @@ -1,81 +1,530 @@ //! Support code for serialization. -#[allow(deprecated_mode)]; - /* Core serialization interfaces. */ +#[forbid(deprecated_mode)]; +#[forbid(non_camel_case_types)]; + pub trait Serializer { // Primitive types: - fn emit_nil(); - fn emit_uint(v: uint); - fn emit_u64(v: u64); - fn emit_u32(v: u32); - fn emit_u16(v: u16); - fn emit_u8(v: u8); - fn emit_int(v: int); - fn emit_i64(v: i64); - fn emit_i32(v: i32); - fn emit_i16(v: i16); - fn emit_i8(v: i8); - fn emit_bool(v: bool); - fn emit_float(v: float); - fn emit_f64(v: f64); - fn emit_f32(v: f32); - fn emit_str(v: &str); + fn emit_nil(&self); + fn emit_uint(&self, v: uint); + fn emit_u64(&self, v: u64); + fn emit_u32(&self, v: u32); + fn emit_u16(&self, v: u16); + fn emit_u8(&self, v: u8); + fn emit_int(&self, v: int); + fn emit_i64(&self, v: i64); + fn emit_i32(&self, v: i32); + fn emit_i16(&self, v: i16); + fn emit_i8(&self, v: i8); + fn emit_bool(&self, v: bool); + fn emit_float(&self, v: float); + fn emit_f64(&self, v: f64); + fn emit_f32(&self, v: f32); + fn emit_char(&self, v: char); + fn emit_borrowed_str(&self, v: &str); + fn emit_owned_str(&self, v: &str); + fn emit_managed_str(&self, v: &str); // Compound types: - fn emit_enum(name: &str, f: fn()); - fn emit_enum_variant(v_name: &str, v_id: uint, sz: uint, f: fn()); - fn emit_enum_variant_arg(idx: uint, f: fn()); - fn emit_vec(len: uint, f: fn()); - fn emit_vec_elt(idx: uint, f: fn()); - fn emit_box(f: fn()); - fn emit_uniq(f: fn()); - fn emit_rec(f: fn()); - fn emit_rec_field(f_name: &str, f_idx: uint, f: fn()); - fn emit_tup(sz: uint, f: fn()); - fn emit_tup_elt(idx: uint, f: fn()); + fn emit_borrowed(&self, f: fn()); + fn emit_owned(&self, f: fn()); + fn emit_managed(&self, f: fn()); + + fn emit_enum(&self, name: &str, f: fn()); + fn emit_enum_variant(&self, v_name: &str, v_id: uint, sz: uint, f: fn()); + fn emit_enum_variant_arg(&self, idx: uint, f: fn()); + + fn emit_borrowed_vec(&self, len: uint, f: fn()); + fn emit_owned_vec(&self, len: uint, f: fn()); + fn emit_managed_vec(&self, len: uint, f: fn()); + fn emit_vec_elt(&self, idx: uint, f: fn()); + + fn emit_rec(&self, f: fn()); + fn emit_struct(&self, name: &str, f: fn()); + fn emit_field(&self, f_name: &str, f_idx: uint, f: fn()); + + fn emit_tup(&self, len: uint, f: fn()); + fn emit_tup_elt(&self, idx: uint, f: fn()); } pub trait Deserializer { // Primitive types: - fn read_nil() -> (); - - fn read_uint() -> uint; - fn read_u64() -> u64; - fn read_u32() -> u32; - fn read_u16() -> u16; - fn read_u8() -> u8; - - fn read_int() -> int; - fn read_i64() -> i64; - fn read_i32() -> i32; - fn read_i16() -> i16; - fn read_i8() -> i8; - - - fn read_bool() -> bool; - - fn read_str() -> ~str; - - fn read_f64() -> f64; - fn read_f32() -> f32; - fn read_float() -> float; + fn read_nil(&self) -> (); + fn read_uint(&self) -> uint; + fn read_u64(&self) -> u64; + fn read_u32(&self) -> u32; + fn read_u16(&self) -> u16; + fn read_u8(&self) -> u8; + fn read_int(&self) -> int; + fn read_i64(&self) -> i64; + fn read_i32(&self) -> i32; + fn read_i16(&self) -> i16; + fn read_i8(&self) -> i8; + fn read_bool(&self) -> bool; + fn read_f64(&self) -> f64; + fn read_f32(&self) -> f32; + fn read_float(&self) -> float; + fn read_char(&self) -> char; + fn read_owned_str(&self) -> ~str; + fn read_managed_str(&self) -> @str; // Compound types: - fn read_enum(name: &str, f: fn() -> T) -> T; - fn read_enum_variant(f: fn(uint) -> T) -> T; - fn read_enum_variant_arg(idx: uint, f: fn() -> T) -> T; - fn read_vec(f: fn(uint) -> T) -> T; - fn read_vec_elt(idx: uint, f: fn() -> T) -> T; - fn read_box(f: fn() -> T) -> T; - fn read_uniq(f: fn() -> T) -> T; - fn read_rec(f: fn() -> T) -> T; - fn read_rec_field(f_name: &str, f_idx: uint, f: fn() -> T) -> T; - fn read_tup(sz: uint, f: fn() -> T) -> T; - fn read_tup_elt(idx: uint, f: fn() -> T) -> T; + fn read_enum(&self, name: &str, f: fn() -> T) -> T; + fn read_enum_variant(&self, f: fn(uint) -> T) -> T; + fn read_enum_variant_arg(&self, idx: uint, f: fn() -> T) -> T; + + fn read_owned(&self, f: fn() -> T) -> T; + fn read_managed(&self, f: fn() -> T) -> T; + + fn read_owned_vec(&self, f: fn(uint) -> T) -> T; + fn read_managed_vec(&self, f: fn(uint) -> T) -> T; + fn read_vec_elt(&self, idx: uint, f: fn() -> T) -> T; + + fn read_rec(&self, f: fn() -> T) -> T; + fn read_struct(&self, name: &str, f: fn() -> T) -> T; + fn read_field(&self, name: &str, idx: uint, f: fn() -> T) -> T; + + fn read_tup(&self, sz: uint, f: fn() -> T) -> T; + fn read_tup_elt(&self, idx: uint, f: fn() -> T) -> T; +} + +pub trait Serializable { + fn serialize(&self, s: &S); +} + +pub trait Deserializable { + static fn deserialize(&self, d: &D) -> self; +} + +pub impl uint: Serializable { + fn serialize(&self, s: &S) { s.emit_uint(*self) } +} + +pub impl uint: Deserializable { + static fn deserialize(&self, d: &D) -> uint { + d.read_uint() + } +} + +pub impl u8: Serializable { + fn serialize(&self, s: &S) { s.emit_u8(*self) } +} + +pub impl u8: Deserializable { + static fn deserialize(&self, d: &D) -> u8 { + d.read_u8() + } +} + +pub impl u16: Serializable { + fn serialize(&self, s: &S) { s.emit_u16(*self) } +} + +pub impl u16: Deserializable { + static fn deserialize(&self, d: &D) -> u16 { + d.read_u16() + } +} + +pub impl u32: Serializable { + fn serialize(&self, s: &S) { s.emit_u32(*self) } +} + +pub impl u32: Deserializable { + static fn deserialize(&self, d: &D) -> u32 { + d.read_u32() + } +} + +pub impl u64: Serializable { + fn serialize(&self, s: &S) { s.emit_u64(*self) } +} + +pub impl u64: Deserializable { + static fn deserialize(&self, d: &D) -> u64 { + d.read_u64() + } +} + +pub impl int: Serializable { + fn serialize(&self, s: &S) { s.emit_int(*self) } +} + +pub impl int: Deserializable { + static fn deserialize(&self, d: &D) -> int { + d.read_int() + } +} + +pub impl i8: Serializable { + fn serialize(&self, s: &S) { s.emit_i8(*self) } +} + +pub impl i8: Deserializable { + static fn deserialize(&self, d: &D) -> i8 { + d.read_i8() + } +} + +pub impl i16: Serializable { + fn serialize(&self, s: &S) { s.emit_i16(*self) } +} + +pub impl i16: Deserializable { + static fn deserialize(&self, d: &D) -> i16 { + d.read_i16() + } +} + +pub impl i32: Serializable { + fn serialize(&self, s: &S) { s.emit_i32(*self) } +} + +pub impl i32: Deserializable { + static fn deserialize(&self, d: &D) -> i32 { + d.read_i32() + } +} + +pub impl i64: Serializable { + fn serialize(&self, s: &S) { s.emit_i64(*self) } +} + +pub impl i64: Deserializable { + static fn deserialize(&self, d: &D) -> i64 { + d.read_i64() + } +} + +pub impl &str: Serializable { + fn serialize(&self, s: &S) { s.emit_borrowed_str(*self) } +} + +pub impl ~str: Serializable { + fn serialize(&self, s: &S) { s.emit_owned_str(*self) } +} + +pub impl ~str: Deserializable { + static fn deserialize(&self, d: &D) -> ~str { + d.read_owned_str() + } +} + +pub impl @str: Serializable { + fn serialize(&self, s: &S) { s.emit_managed_str(*self) } +} + +pub impl @str: Deserializable { + static fn deserialize(&self, d: &D) -> @str { + d.read_managed_str() + } +} + +pub impl float: Serializable { + fn serialize(&self, s: &S) { s.emit_float(*self) } +} + +pub impl float: Deserializable { + static fn deserialize(&self, d: &D) -> float { + d.read_float() + } +} + +pub impl f32: Serializable { + fn serialize(&self, s: &S) { s.emit_f32(*self) } +} + +pub impl f32: Deserializable { + static fn deserialize(&self, d: &D) -> f32 { + d.read_f32() } +} + +pub impl f64: Serializable { + fn serialize(&self, s: &S) { s.emit_f64(*self) } +} + +pub impl f64: Deserializable { + static fn deserialize(&self, d: &D) -> f64 { + d.read_f64() + } +} + +pub impl bool: Serializable { + fn serialize(&self, s: &S) { s.emit_bool(*self) } +} + +pub impl bool: Deserializable { + static fn deserialize(&self, d: &D) -> bool { + d.read_bool() + } +} + +pub impl (): Serializable { + fn serialize(&self, s: &S) { s.emit_nil() } +} + +pub impl (): Deserializable { + static fn deserialize(&self, d: &D) -> () { + d.read_nil() + } +} + +pub impl &T: Serializable { + fn serialize(&self, s: &S) { + s.emit_borrowed(|| (**self).serialize(s)) + } +} + +pub impl ~T: Serializable { + fn serialize(&self, s: &S) { + s.emit_owned(|| (**self).serialize(s)) + } +} + +pub impl ~T: Deserializable { + static fn deserialize(&self, d: &D) -> ~T { + d.read_owned(|| ~deserialize(d)) + } +} + +pub impl @T: Serializable { + fn serialize(&self, s: &S) { + s.emit_managed(|| (**self).serialize(s)) + } +} + +pub impl @T: Deserializable { + static fn deserialize(&self, d: &D) -> @T { + d.read_managed(|| @deserialize(d)) + } +} + +pub impl &[T]: Serializable { + fn serialize(&self, s: &S) { + do s.emit_borrowed_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl ~[T]: Serializable { + fn serialize(&self, s: &S) { + do s.emit_owned_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl ~[T]: Deserializable { + static fn deserialize(&self, d: &D) -> ~[T] { + do d.read_owned_vec |len| { + do vec::from_fn(len) |i| { + d.read_vec_elt(i, || deserialize(d)) + } + } + } +} + +pub impl @[T]: Serializable { + fn serialize(&self, s: &S) { + do s.emit_managed_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl @[T]: Deserializable { + static fn deserialize(&self, d: &D) -> @[T] { + do d.read_managed_vec |len| { + do at_vec::from_fn(len) |i| { + d.read_vec_elt(i, || deserialize(d)) + } + } + } +} + +pub impl Option: Serializable { + fn serialize(&self, s: &S) { + do s.emit_enum(~"option") { + match *self { + None => do s.emit_enum_variant(~"none", 0u, 0u) { + }, + + Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { + s.emit_enum_variant_arg(0u, || v.serialize(s)) + } + } + } + } +} + +pub impl Option: Deserializable { + static fn deserialize(&self, d: &D) -> Option { + do d.read_enum(~"option") { + do d.read_enum_variant |i| { + match i { + 0 => None, + 1 => Some(d.read_enum_variant_arg(0u, || deserialize(d))), + _ => fail(#fmt("Bad variant for option: %u", i)) + } + } + } + } +} + +pub impl< + T0: Serializable, + T1: Serializable +> (T0, T1): Serializable { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1) => { + do s.emit_tup(2) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + } + } + } + } +} + +pub impl< + T0: Deserializable, + T1: Deserializable +> (T0, T1): Deserializable { + static fn deserialize(&self, d: &D) -> (T0, T1) { + do d.read_tup(2) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)) + ) + } + } +} + +pub impl< + T0: Serializable, + T1: Serializable, + T2: Serializable +> (T0, T1, T2): Serializable { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2) => { + do s.emit_tup(3) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + } + } + } + } +} + +pub impl< + T0: Deserializable, + T1: Deserializable, + T2: Deserializable +> (T0, T1, T2): Deserializable { + static fn deserialize(&self, d: &D) -> (T0, T1, T2) { + do d.read_tup(3) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)) + ) + } + } +} + +pub impl< + T0: Serializable, + T1: Serializable, + T2: Serializable, + T3: Serializable +> (T0, T1, T2, T3): Serializable { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2, ref t3) => { + do s.emit_tup(4) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + s.emit_tup_elt(3, || t3.serialize(s)); + } + } + } + } +} + +pub impl< + T0: Deserializable, + T1: Deserializable, + T2: Deserializable, + T3: Deserializable +> (T0, T1, T2, T3): Deserializable { + static fn deserialize(&self, d: &D) -> (T0, T1, T2, T3) { + do d.read_tup(4) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)), + d.read_tup_elt(3, || deserialize(d)) + ) + } + } +} + +pub impl< + T0: Serializable, + T1: Serializable, + T2: Serializable, + T3: Serializable, + T4: Serializable +> (T0, T1, T2, T3, T4): Serializable { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2, ref t3, ref t4) => { + do s.emit_tup(5) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + s.emit_tup_elt(3, || t3.serialize(s)); + s.emit_tup_elt(4, || t4.serialize(s)); + } + } + } + } +} + +pub impl< + T0: Deserializable, + T1: Deserializable, + T2: Deserializable, + T3: Deserializable, + T4: Deserializable +> (T0, T1, T2, T3, T4): Deserializable { + static fn deserialize(&self, d: &D) + -> (T0, T1, T2, T3, T4) { + do d.read_tup(5) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)), + d.read_tup_elt(3, || deserialize(d)), + d.read_tup_elt(4, || deserialize(d)) + ) + } + } } // ___________________________________________________________________________ @@ -83,188 +532,31 @@ pub trait Deserializer { // // In some cases, these should eventually be coded as traits. -pub fn emit_from_vec(&&s: S, &&v: ~[T], f: fn(&&x: T)) { - do s.emit_vec(vec::len(v)) { - for vec::eachi(v) |i,e| { - do s.emit_vec_elt(i) { - f(*e) +pub trait SerializerHelpers { + fn emit_from_vec(&self, v: &[T], f: fn(&T)); +} + +pub impl S: SerializerHelpers { + fn emit_from_vec(&self, v: &[T], f: fn(&T)) { + do self.emit_owned_vec(v.len()) { + for v.eachi |i, e| { + do self.emit_vec_elt(i) { + f(e) + } } } } } -pub fn read_to_vec(&&d: D, f: fn() -> T) -> ~[T] { - do d.read_vec |len| { - do vec::from_fn(len) |i| { - d.read_vec_elt(i, || f()) - } - } -} - -pub trait SerializerHelpers { - fn emit_from_vec(&&v: ~[T], f: fn(&&x: T)); -} - -impl S: SerializerHelpers { - fn emit_from_vec(&&v: ~[T], f: fn(&&x: T)) { - emit_from_vec(self, v, f) - } -} - pub trait DeserializerHelpers { - fn read_to_vec(f: fn() -> T) -> ~[T]; + fn read_to_vec(&self, f: fn() -> T) -> ~[T]; } -impl D: DeserializerHelpers { - fn read_to_vec(f: fn() -> T) -> ~[T] { - read_to_vec(self, f) - } -} - -pub fn serialize_uint(&&s: S, v: uint) { - s.emit_uint(v); -} - -pub fn deserialize_uint(&&d: D) -> uint { - d.read_uint() -} - -pub fn serialize_u8(&&s: S, v: u8) { - s.emit_u8(v); -} - -pub fn deserialize_u8(&&d: D) -> u8 { - d.read_u8() -} - -pub fn serialize_u16(&&s: S, v: u16) { - s.emit_u16(v); -} - -pub fn deserialize_u16(&&d: D) -> u16 { - d.read_u16() -} - -pub fn serialize_u32(&&s: S, v: u32) { - s.emit_u32(v); -} - -pub fn deserialize_u32(&&d: D) -> u32 { - d.read_u32() -} - -pub fn serialize_u64(&&s: S, v: u64) { - s.emit_u64(v); -} - -pub fn deserialize_u64(&&d: D) -> u64 { - d.read_u64() -} - -pub fn serialize_int(&&s: S, v: int) { - s.emit_int(v); -} - -pub fn deserialize_int(&&d: D) -> int { - d.read_int() -} - -pub fn serialize_i8(&&s: S, v: i8) { - s.emit_i8(v); -} - -pub fn deserialize_i8(&&d: D) -> i8 { - d.read_i8() -} - -pub fn serialize_i16(&&s: S, v: i16) { - s.emit_i16(v); -} - -pub fn deserialize_i16(&&d: D) -> i16 { - d.read_i16() -} - -pub fn serialize_i32(&&s: S, v: i32) { - s.emit_i32(v); -} - -pub fn deserialize_i32(&&d: D) -> i32 { - d.read_i32() -} - -pub fn serialize_i64(&&s: S, v: i64) { - s.emit_i64(v); -} - -pub fn deserialize_i64(&&d: D) -> i64 { - d.read_i64() -} - -pub fn serialize_str(&&s: S, v: &str) { - s.emit_str(v); -} - -pub fn deserialize_str(&&d: D) -> ~str { - d.read_str() -} - -pub fn serialize_float(&&s: S, v: float) { - s.emit_float(v); -} - -pub fn deserialize_float(&&d: D) -> float { - d.read_float() -} - -pub fn serialize_f32(&&s: S, v: f32) { - s.emit_f32(v); -} - -pub fn deserialize_f32(&&d: D) -> f32 { - d.read_f32() -} - -pub fn serialize_f64(&&s: S, v: f64) { - s.emit_f64(v); -} - -pub fn deserialize_f64(&&d: D) -> f64 { - d.read_f64() -} - -pub fn serialize_bool(&&s: S, v: bool) { - s.emit_bool(v); -} - -pub fn deserialize_bool(&&d: D) -> bool { - d.read_bool() -} - -pub fn serialize_Option(&&s: S, &&v: Option, - st: fn(&&x: T)) { - do s.emit_enum(~"option") { - match v { - None => do s.emit_enum_variant(~"none", 0u, 0u) { - }, - - Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { - do s.emit_enum_variant_arg(0u) { - st(*v) - } - } - } - } -} - -pub fn deserialize_Option(&&d: D, st: fn() -> T) - -> Option { - do d.read_enum(~"option") { - do d.read_enum_variant |i| { - match i { - 0 => None, - 1 => Some(d.read_enum_variant_arg(0u, || st() )), - _ => fail(#fmt("Bad variant for option: %u", i)) +pub impl D: DeserializerHelpers { + fn read_to_vec(&self, f: fn() -> T) -> ~[T] { + do self.read_owned_vec |len| { + do vec::from_fn(len) |i| { + self.read_vec_elt(i, || f()) } } } diff --git a/src/libstd/serialization2.rs b/src/libstd/serialization2.rs index 5173ef163a22..9ea544778694 100644 --- a/src/libstd/serialization2.rs +++ b/src/libstd/serialization2.rs @@ -4,560 +4,4 @@ Core serialization interfaces. */ -#[forbid(deprecated_mode)]; -#[forbid(non_camel_case_types)]; - -pub trait Serializer { - // Primitive types: - fn emit_nil(&self); - fn emit_uint(&self, v: uint); - fn emit_u64(&self, v: u64); - fn emit_u32(&self, v: u32); - fn emit_u16(&self, v: u16); - fn emit_u8(&self, v: u8); - fn emit_int(&self, v: int); - fn emit_i64(&self, v: i64); - fn emit_i32(&self, v: i32); - fn emit_i16(&self, v: i16); - fn emit_i8(&self, v: i8); - fn emit_bool(&self, v: bool); - fn emit_float(&self, v: float); - fn emit_f64(&self, v: f64); - fn emit_f32(&self, v: f32); - fn emit_char(&self, v: char); - fn emit_borrowed_str(&self, v: &str); - fn emit_owned_str(&self, v: &str); - fn emit_managed_str(&self, v: &str); - - // Compound types: - fn emit_borrowed(&self, f: fn()); - fn emit_owned(&self, f: fn()); - fn emit_managed(&self, f: fn()); - - fn emit_enum(&self, name: &str, f: fn()); - fn emit_enum_variant(&self, v_name: &str, v_id: uint, sz: uint, f: fn()); - fn emit_enum_variant_arg(&self, idx: uint, f: fn()); - - fn emit_borrowed_vec(&self, len: uint, f: fn()); - fn emit_owned_vec(&self, len: uint, f: fn()); - fn emit_managed_vec(&self, len: uint, f: fn()); - fn emit_vec_elt(&self, idx: uint, f: fn()); - - fn emit_rec(&self, f: fn()); - fn emit_struct(&self, name: &str, f: fn()); - fn emit_field(&self, f_name: &str, f_idx: uint, f: fn()); - - fn emit_tup(&self, len: uint, f: fn()); - fn emit_tup_elt(&self, idx: uint, f: fn()); -} - -pub trait Deserializer { - // Primitive types: - fn read_nil(&self) -> (); - fn read_uint(&self) -> uint; - fn read_u64(&self) -> u64; - fn read_u32(&self) -> u32; - fn read_u16(&self) -> u16; - fn read_u8(&self) -> u8; - fn read_int(&self) -> int; - fn read_i64(&self) -> i64; - fn read_i32(&self) -> i32; - fn read_i16(&self) -> i16; - fn read_i8(&self) -> i8; - fn read_bool(&self) -> bool; - fn read_f64(&self) -> f64; - fn read_f32(&self) -> f32; - fn read_float(&self) -> float; - fn read_char(&self) -> char; - fn read_owned_str(&self) -> ~str; - fn read_managed_str(&self) -> @str; - - // Compound types: - fn read_enum(&self, name: &str, f: fn() -> T) -> T; - fn read_enum_variant(&self, f: fn(uint) -> T) -> T; - fn read_enum_variant_arg(&self, idx: uint, f: fn() -> T) -> T; - - fn read_owned(&self, f: fn() -> T) -> T; - fn read_managed(&self, f: fn() -> T) -> T; - - fn read_owned_vec(&self, f: fn(uint) -> T) -> T; - fn read_managed_vec(&self, f: fn(uint) -> T) -> T; - fn read_vec_elt(&self, idx: uint, f: fn() -> T) -> T; - - fn read_rec(&self, f: fn() -> T) -> T; - fn read_struct(&self, name: &str, f: fn() -> T) -> T; - fn read_field(&self, name: &str, idx: uint, f: fn() -> T) -> T; - - fn read_tup(&self, sz: uint, f: fn() -> T) -> T; - fn read_tup_elt(&self, idx: uint, f: fn() -> T) -> T; -} - -pub trait Serializable { - fn serialize(&self, s: &S); -} - -pub trait Deserializable { - static fn deserialize(&self, d: &D) -> self; -} - -pub impl uint: Serializable { - fn serialize(&self, s: &S) { s.emit_uint(*self) } -} - -pub impl uint: Deserializable { - static fn deserialize(&self, d: &D) -> uint { - d.read_uint() - } -} - -pub impl u8: Serializable { - fn serialize(&self, s: &S) { s.emit_u8(*self) } -} - -pub impl u8: Deserializable { - static fn deserialize(&self, d: &D) -> u8 { - d.read_u8() - } -} - -pub impl u16: Serializable { - fn serialize(&self, s: &S) { s.emit_u16(*self) } -} - -pub impl u16: Deserializable { - static fn deserialize(&self, d: &D) -> u16 { - d.read_u16() - } -} - -pub impl u32: Serializable { - fn serialize(&self, s: &S) { s.emit_u32(*self) } -} - -pub impl u32: Deserializable { - static fn deserialize(&self, d: &D) -> u32 { - d.read_u32() - } -} - -pub impl u64: Serializable { - fn serialize(&self, s: &S) { s.emit_u64(*self) } -} - -pub impl u64: Deserializable { - static fn deserialize(&self, d: &D) -> u64 { - d.read_u64() - } -} - -pub impl int: Serializable { - fn serialize(&self, s: &S) { s.emit_int(*self) } -} - -pub impl int: Deserializable { - static fn deserialize(&self, d: &D) -> int { - d.read_int() - } -} - -pub impl i8: Serializable { - fn serialize(&self, s: &S) { s.emit_i8(*self) } -} - -pub impl i8: Deserializable { - static fn deserialize(&self, d: &D) -> i8 { - d.read_i8() - } -} - -pub impl i16: Serializable { - fn serialize(&self, s: &S) { s.emit_i16(*self) } -} - -pub impl i16: Deserializable { - static fn deserialize(&self, d: &D) -> i16 { - d.read_i16() - } -} - -pub impl i32: Serializable { - fn serialize(&self, s: &S) { s.emit_i32(*self) } -} - -pub impl i32: Deserializable { - static fn deserialize(&self, d: &D) -> i32 { - d.read_i32() - } -} - -pub impl i64: Serializable { - fn serialize(&self, s: &S) { s.emit_i64(*self) } -} - -pub impl i64: Deserializable { - static fn deserialize(&self, d: &D) -> i64 { - d.read_i64() - } -} - -pub impl &str: Serializable { - fn serialize(&self, s: &S) { s.emit_borrowed_str(*self) } -} - -pub impl ~str: Serializable { - fn serialize(&self, s: &S) { s.emit_owned_str(*self) } -} - -pub impl ~str: Deserializable { - static fn deserialize(&self, d: &D) -> ~str { - d.read_owned_str() - } -} - -pub impl @str: Serializable { - fn serialize(&self, s: &S) { s.emit_managed_str(*self) } -} - -pub impl @str: Deserializable { - static fn deserialize(&self, d: &D) -> @str { - d.read_managed_str() - } -} - -pub impl float: Serializable { - fn serialize(&self, s: &S) { s.emit_float(*self) } -} - -pub impl float: Deserializable { - static fn deserialize(&self, d: &D) -> float { - d.read_float() - } -} - -pub impl f32: Serializable { - fn serialize(&self, s: &S) { s.emit_f32(*self) } -} - -pub impl f32: Deserializable { - static fn deserialize(&self, d: &D) -> f32 { - d.read_f32() } -} - -pub impl f64: Serializable { - fn serialize(&self, s: &S) { s.emit_f64(*self) } -} - -pub impl f64: Deserializable { - static fn deserialize(&self, d: &D) -> f64 { - d.read_f64() - } -} - -pub impl bool: Serializable { - fn serialize(&self, s: &S) { s.emit_bool(*self) } -} - -pub impl bool: Deserializable { - static fn deserialize(&self, d: &D) -> bool { - d.read_bool() - } -} - -pub impl (): Serializable { - fn serialize(&self, s: &S) { s.emit_nil() } -} - -pub impl (): Deserializable { - static fn deserialize(&self, d: &D) -> () { - d.read_nil() - } -} - -pub impl &T: Serializable { - fn serialize(&self, s: &S) { - s.emit_borrowed(|| (**self).serialize(s)) - } -} - -pub impl ~T: Serializable { - fn serialize(&self, s: &S) { - s.emit_owned(|| (**self).serialize(s)) - } -} - -pub impl ~T: Deserializable { - static fn deserialize(&self, d: &D) -> ~T { - d.read_owned(|| ~deserialize(d)) - } -} - -pub impl @T: Serializable { - fn serialize(&self, s: &S) { - s.emit_managed(|| (**self).serialize(s)) - } -} - -pub impl @T: Deserializable { - static fn deserialize(&self, d: &D) -> @T { - d.read_managed(|| @deserialize(d)) - } -} - -pub impl &[T]: Serializable { - fn serialize(&self, s: &S) { - do s.emit_borrowed_vec(self.len()) { - for self.eachi |i, e| { - s.emit_vec_elt(i, || e.serialize(s)) - } - } - } -} - -pub impl ~[T]: Serializable { - fn serialize(&self, s: &S) { - do s.emit_owned_vec(self.len()) { - for self.eachi |i, e| { - s.emit_vec_elt(i, || e.serialize(s)) - } - } - } -} - -pub impl ~[T]: Deserializable { - static fn deserialize(&self, d: &D) -> ~[T] { - do d.read_owned_vec |len| { - do vec::from_fn(len) |i| { - d.read_vec_elt(i, || deserialize(d)) - } - } - } -} - -pub impl @[T]: Serializable { - fn serialize(&self, s: &S) { - do s.emit_managed_vec(self.len()) { - for self.eachi |i, e| { - s.emit_vec_elt(i, || e.serialize(s)) - } - } - } -} - -pub impl @[T]: Deserializable { - static fn deserialize(&self, d: &D) -> @[T] { - do d.read_managed_vec |len| { - do at_vec::from_fn(len) |i| { - d.read_vec_elt(i, || deserialize(d)) - } - } - } -} - -pub impl Option: Serializable { - fn serialize(&self, s: &S) { - do s.emit_enum(~"option") { - match *self { - None => do s.emit_enum_variant(~"none", 0u, 0u) { - }, - - Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { - s.emit_enum_variant_arg(0u, || v.serialize(s)) - } - } - } - } -} - -pub impl Option: Deserializable { - static fn deserialize(&self, d: &D) -> Option { - do d.read_enum(~"option") { - do d.read_enum_variant |i| { - match i { - 0 => None, - 1 => Some(d.read_enum_variant_arg(0u, || deserialize(d))), - _ => fail(#fmt("Bad variant for option: %u", i)) - } - } - } - } -} - -pub impl< - T0: Serializable, - T1: Serializable -> (T0, T1): Serializable { - fn serialize(&self, s: &S) { - match *self { - (ref t0, ref t1) => { - do s.emit_tup(2) { - s.emit_tup_elt(0, || t0.serialize(s)); - s.emit_tup_elt(1, || t1.serialize(s)); - } - } - } - } -} - -pub impl< - T0: Deserializable, - T1: Deserializable -> (T0, T1): Deserializable { - static fn deserialize(&self, d: &D) -> (T0, T1) { - do d.read_tup(2) { - ( - d.read_tup_elt(0, || deserialize(d)), - d.read_tup_elt(1, || deserialize(d)) - ) - } - } -} - -pub impl< - T0: Serializable, - T1: Serializable, - T2: Serializable -> (T0, T1, T2): Serializable { - fn serialize(&self, s: &S) { - match *self { - (ref t0, ref t1, ref t2) => { - do s.emit_tup(3) { - s.emit_tup_elt(0, || t0.serialize(s)); - s.emit_tup_elt(1, || t1.serialize(s)); - s.emit_tup_elt(2, || t2.serialize(s)); - } - } - } - } -} - -pub impl< - T0: Deserializable, - T1: Deserializable, - T2: Deserializable -> (T0, T1, T2): Deserializable { - static fn deserialize(&self, d: &D) -> (T0, T1, T2) { - do d.read_tup(3) { - ( - d.read_tup_elt(0, || deserialize(d)), - d.read_tup_elt(1, || deserialize(d)), - d.read_tup_elt(2, || deserialize(d)) - ) - } - } -} - -pub impl< - T0: Serializable, - T1: Serializable, - T2: Serializable, - T3: Serializable -> (T0, T1, T2, T3): Serializable { - fn serialize(&self, s: &S) { - match *self { - (ref t0, ref t1, ref t2, ref t3) => { - do s.emit_tup(4) { - s.emit_tup_elt(0, || t0.serialize(s)); - s.emit_tup_elt(1, || t1.serialize(s)); - s.emit_tup_elt(2, || t2.serialize(s)); - s.emit_tup_elt(3, || t3.serialize(s)); - } - } - } - } -} - -pub impl< - T0: Deserializable, - T1: Deserializable, - T2: Deserializable, - T3: Deserializable -> (T0, T1, T2, T3): Deserializable { - static fn deserialize(&self, d: &D) -> (T0, T1, T2, T3) { - do d.read_tup(4) { - ( - d.read_tup_elt(0, || deserialize(d)), - d.read_tup_elt(1, || deserialize(d)), - d.read_tup_elt(2, || deserialize(d)), - d.read_tup_elt(3, || deserialize(d)) - ) - } - } -} - -pub impl< - T0: Serializable, - T1: Serializable, - T2: Serializable, - T3: Serializable, - T4: Serializable -> (T0, T1, T2, T3, T4): Serializable { - fn serialize(&self, s: &S) { - match *self { - (ref t0, ref t1, ref t2, ref t3, ref t4) => { - do s.emit_tup(5) { - s.emit_tup_elt(0, || t0.serialize(s)); - s.emit_tup_elt(1, || t1.serialize(s)); - s.emit_tup_elt(2, || t2.serialize(s)); - s.emit_tup_elt(3, || t3.serialize(s)); - s.emit_tup_elt(4, || t4.serialize(s)); - } - } - } - } -} - -pub impl< - T0: Deserializable, - T1: Deserializable, - T2: Deserializable, - T3: Deserializable, - T4: Deserializable -> (T0, T1, T2, T3, T4): Deserializable { - static fn deserialize(&self, d: &D) - -> (T0, T1, T2, T3, T4) { - do d.read_tup(5) { - ( - d.read_tup_elt(0, || deserialize(d)), - d.read_tup_elt(1, || deserialize(d)), - d.read_tup_elt(2, || deserialize(d)), - d.read_tup_elt(3, || deserialize(d)), - d.read_tup_elt(4, || deserialize(d)) - ) - } - } -} - -// ___________________________________________________________________________ -// Helper routines -// -// In some cases, these should eventually be coded as traits. - -pub trait SerializerHelpers { - fn emit_from_vec(&self, v: &[T], f: fn(&T)); -} - -pub impl S: SerializerHelpers { - fn emit_from_vec(&self, v: &[T], f: fn(&T)) { - do self.emit_owned_vec(v.len()) { - for v.eachi |i, e| { - do self.emit_vec_elt(i) { - f(e) - } - } - } - } -} - -pub trait DeserializerHelpers { - fn read_to_vec(&self, f: fn() -> T) -> ~[T]; -} - -pub impl D: DeserializerHelpers { - fn read_to_vec(&self, f: fn() -> T) -> ~[T] { - do self.read_owned_vec |len| { - do vec::from_fn(len) |i| { - self.read_vec_elt(i, || f()) - } - } - } -} +pub use serialization::*; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1c279f81cc39..f3e118461e66 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1,9 +1,9 @@ // The Rust abstract syntax tree. -use std::serialization2::{Serializable, - Deserializable, - Serializer, - Deserializer}; +use std::serialization::{Serializable, + Deserializable, + Serializer, + Deserializer}; use codemap::{span, filename}; use parse::token; @@ -18,6 +18,8 @@ impl span: Deserializable { } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type spanned = {node: T, span: span}; @@ -74,6 +76,8 @@ impl ident: to_bytes::IterBytes { // Functions may or may not have names. type fn_ident = Option; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type path = {span: span, @@ -86,6 +90,8 @@ type crate_num = int; type node_id = int; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type def_id = {crate: crate_num, node: node_id}; @@ -100,6 +106,8 @@ impl def_id : cmp::Eq { const local_crate: crate_num = 0; const crate_node_id: node_id = 0; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum ty_param_bound { @@ -110,10 +118,14 @@ enum ty_param_bound { bound_trait(@ty), } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum def { @@ -294,6 +306,8 @@ type crate_directive = spanned; type meta_item = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum meta_item_ { @@ -304,6 +318,8 @@ enum meta_item_ { type blk = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type blk_ = {view_items: ~[@view_item], @@ -312,14 +328,20 @@ type blk_ = {view_items: ~[@view_item], id: node_id, rules: blk_check_mode}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type pat = {id: node_id, node: pat_, span: span}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type field_pat = {ident: ident, pat: @pat}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum binding_mode { @@ -377,6 +399,8 @@ impl binding_mode : cmp::Eq { pure fn ne(other: &binding_mode) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum pat_ { @@ -401,6 +425,8 @@ enum pat_ { pat_range(@expr, @expr), } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum mutability { m_mutbl, m_imm, m_const, } @@ -418,6 +444,8 @@ impl mutability : cmp::Eq { pure fn ne(other: &mutability) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum proto { @@ -434,6 +462,8 @@ impl proto : cmp::Eq { pure fn ne(other: &proto) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum vstore { @@ -444,6 +474,8 @@ enum vstore { vstore_slice(@region) // &[1,2,3,4](foo)? } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum expr_vstore { @@ -461,6 +493,8 @@ pure fn is_blockish(p: ast::proto) -> bool { } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum binop { @@ -491,6 +525,8 @@ impl binop : cmp::Eq { pure fn ne(other: &binop) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum unop { @@ -543,6 +579,8 @@ impl unop : cmp::Eq { // Generally, after typeck you can get the inferred value // using ty::resolved_T(...). +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum inferable { @@ -583,6 +621,8 @@ impl inferable : cmp::Eq { } // "resolved" mode: the real modes. +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum rmode { by_ref, by_val, by_move, by_copy } @@ -606,6 +646,8 @@ type mode = inferable; type stmt = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum stmt_ { @@ -618,6 +660,8 @@ enum stmt_ { stmt_semi(@expr, node_id), } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum init_op { init_assign, init_move, } @@ -642,12 +686,16 @@ impl init_op : cmp::Eq { pure fn ne(other: &init_op) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type initializer = {op: init_op, expr: @expr}; // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type local_ = {is_mutbl: bool, ty: @ty, pat: @pat, @@ -657,20 +705,28 @@ type local = spanned; type decl = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum decl_ { decl_local(~[@local]), decl_item(@item), } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type field_ = {mutbl: mutability, ident: ident, expr: @expr}; type field = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum blk_check_mode { default_blk, unsafe_blk, } @@ -687,20 +743,28 @@ impl blk_check_mode : cmp::Eq { pure fn ne(other: &blk_check_mode) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type expr = {id: node_id, callee_id: node_id, node: expr_, span: span}; // Extra node ID is only used for index, assign_op, unary, binary +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum log_level { error, debug, other } // 0 = error, 1 = debug, 2 = other +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum alt_mode { alt_check, alt_exhaustive, } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum expr_ { @@ -758,6 +822,8 @@ enum expr_ { expr_repeat(@expr /* element */, @expr /* count */, mutability) } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type capture_item_ = { @@ -787,6 +853,8 @@ type capture_clause = @~[capture_item]; // else knows what to do with them, so you'll probably get a syntax // error. // +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] #[doc="For macro invocations; parsing is delegated to the macro"] @@ -852,6 +920,8 @@ enum token_tree { // type matcher = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum matcher_ { @@ -868,12 +938,16 @@ type mac = spanned; type mac_arg = Option<@expr>; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type mac_body_ = {span: span}; type mac_body = Option; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum mac_ { @@ -888,6 +962,8 @@ enum mac_ { type lit = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum lit_ { @@ -930,22 +1006,30 @@ impl ast::lit_: cmp::Eq { // NB: If you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type mt = {ty: @ty, mutbl: mutability}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type ty_field_ = {ident: ident, mt: mt}; type ty_field = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type ty_method = {ident: ident, attrs: ~[attribute], purity: purity, decl: fn_decl, tps: ~[ty_param], self_ty: self_ty, id: node_id, span: span}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] // A trait method is either required (meaning it doesn't have an @@ -956,6 +1040,8 @@ enum trait_method { provided(@method), } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } @@ -986,6 +1072,8 @@ impl int_ty : cmp::Eq { pure fn ne(other: &int_ty) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } @@ -1014,6 +1102,8 @@ impl uint_ty : cmp::Eq { pure fn ne(other: &uint_ty) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum float_ty { ty_f, ty_f32, ty_f64, } @@ -1033,11 +1123,15 @@ impl float_ty : cmp::Eq { pure fn ne(other: &float_ty) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type ty = {id: node_id, node: ty_, span: span}; // Not represented directly in the AST, referred to by name through a ty_path. +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum prim_ty { @@ -1086,10 +1180,14 @@ impl prim_ty : cmp::Eq { pure fn ne(other: &prim_ty) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type region = {id: node_id, node: region_}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum region_ { @@ -1099,6 +1197,8 @@ enum region_ { re_named(ident) } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum ty_ { @@ -1139,10 +1239,14 @@ impl ty : to_bytes::IterBytes { } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type fn_decl = @@ -1150,6 +1254,8 @@ type fn_decl = output: @ty, cf: ret_style}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum purity { @@ -1172,6 +1278,8 @@ impl purity : cmp::Eq { pure fn ne(other: &purity) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum ret_style { @@ -1198,6 +1306,8 @@ impl ret_style : cmp::Eq { pure fn ne(other: &ret_style) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum self_ty_ { @@ -1255,6 +1365,8 @@ impl self_ty_ : cmp::Eq { type self_ty = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type method = {ident: ident, attrs: ~[attribute], @@ -1263,10 +1375,14 @@ type method = {ident: ident, attrs: ~[attribute], id: node_id, span: span, self_id: node_id, vis: visibility}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type _mod = {view_items: ~[@view_item], items: ~[@item]}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum foreign_abi { @@ -1276,6 +1392,8 @@ enum foreign_abi { } // Foreign mods can be named or anonymous +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum foreign_mod_sort { named, anonymous } @@ -1301,6 +1419,8 @@ impl foreign_abi : cmp::Eq { pure fn ne(other: &foreign_abi) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type foreign_mod = @@ -1308,10 +1428,14 @@ type foreign_mod = view_items: ~[@view_item], items: ~[@foreign_item]}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type variant_arg = {ty: @ty, id: node_id}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum variant_kind { @@ -1320,14 +1444,20 @@ enum variant_kind { enum_variant_kind(enum_def) } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type enum_def_ = { variants: ~[variant], common: Option<@struct_def> }; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum enum_def = enum_def_; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, @@ -1335,12 +1465,16 @@ type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, type variant = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type path_list_ident_ = {name: ident, id: node_id}; type path_list_ident = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum namespace { module_ns, type_value_ns } @@ -1354,6 +1488,8 @@ impl namespace : cmp::Eq { type view_path = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum view_path_ { @@ -1372,11 +1508,15 @@ enum view_path_ { view_path_list(@path, ~[path_list_ident], node_id) } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type view_item = {node: view_item_, attrs: ~[attribute], vis: visibility, span: span}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum view_item_ { @@ -1391,6 +1531,8 @@ type attribute = spanned; // Distinguishes between attributes that decorate items and attributes that // are contained as statements within items. These two cases need to be // distinguished for pretty-printing. +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum attr_style { attr_outer, attr_inner, } @@ -1403,6 +1545,8 @@ impl attr_style : cmp::Eq { } // doc-comments are promoted to attributes that have is_sugared_doc = true +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; @@ -1416,10 +1560,14 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; conceptually, the impl_id stands in for the pair of (this class, this trait) */ +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum visibility { public, private, inherited } @@ -1438,6 +1586,8 @@ impl visibility : cmp::Eq { pure fn ne(other: &visibility) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type struct_field_ = { @@ -1448,6 +1598,8 @@ type struct_field_ = { type struct_field = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum struct_field_kind { @@ -1455,6 +1607,8 @@ enum struct_field_kind { unnamed_field // element of a tuple-like struct } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type struct_def = { @@ -1472,12 +1626,16 @@ type struct_def = { FIXME (#3300): Should allow items to be anonymous. Right now we just use dummy names for anon items. */ +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type item = {ident: ident, attrs: ~[attribute], id: node_id, node: item_, vis: visibility, span: span}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum item_ { @@ -1496,6 +1654,8 @@ enum item_ { item_mac(mac), } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum class_mutability { class_mutable, class_immutable } @@ -1520,6 +1680,8 @@ impl class_mutability : cmp::Eq { type class_ctor = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type class_ctor_ = {id: node_id, @@ -1530,6 +1692,8 @@ type class_ctor_ = {id: node_id, type class_dtor = spanned; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type class_dtor_ = {id: node_id, @@ -1537,6 +1701,8 @@ type class_dtor_ = {id: node_id, self_id: node_id, body: blk}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type foreign_item = @@ -1547,6 +1713,8 @@ type foreign_item = span: span, vis: visibility}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum foreign_item_ { @@ -1557,6 +1725,8 @@ enum foreign_item_ { // The data we save and restore about an inlined item or method. This is not // part of the AST that we parse from a file, but it becomes part of the tree // that we trans. +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum inlined_item { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 47cbdb7ac6cb..897a51f710c6 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -406,6 +406,8 @@ fn dtor_dec() -> fn_decl { // ______________________________________________________________________ // Enumerating the IDs which appear in an AST +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type id_range = {min: node_id, max: node_id}; diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 63a6551bf888..b06536f4e026 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -1,62 +1,64 @@ /* -The compiler code necessary to implement the #[auto_serialize] -extension. The idea here is that type-defining items may be tagged -with #[auto_serialize], which will cause us to generate a little -companion module with the same name as the item. +The compiler code necessary to implement the #[auto_serialize] and +#[auto_deserialize] extension. The idea here is that type-defining items may +be tagged with #[auto_serialize] and #[auto_deserialize], which will cause +us to generate a little companion module with the same name as the item. For example, a type like: - type node_id = uint; + #[auto_serialize] + #[auto_deserialize] + struct Node {id: uint} -would generate two functions like: +would generate two implementations like: - fn serialize_node_id(s: S, v: node_id) { - s.emit_uint(v); + impl Node: Serializable { + fn serialize(s: &S) { + do s.emit_struct("Node") { + s.emit_field("id", 0, || s.emit_uint(self)) + } + } } - fn deserialize_node_id(d: D) -> node_id { - d.read_uint() + + impl node_id: Deserializable { + static fn deserialize(d: &D) -> Node { + do d.read_struct("Node") { + Node { + id: d.read_field(~"x", 0, || deserialize(d)) + } + } + } } Other interesting scenarios are whe the item has type parameters or references other non-built-in types. A type definition like: + #[auto_serialize] + #[auto_deserialize] type spanned = {node: T, span: span}; would yield functions like: - fn serialize_spanned(s: S, v: spanned, t: fn(T)) { - s.emit_rec(2u) {|| - s.emit_rec_field("node", 0u) {|| - t(s.node); - }; - s.emit_rec_field("span", 1u) {|| - serialize_span(s, s.span); - }; - } - } - fn deserialize_spanned(d: D, t: fn() -> T) -> node_id { - d.read_rec(2u) {|| - {node: d.read_rec_field("node", 0u, t), - span: d.read_rec_field("span", 1u) {||deserialize_span(d)}} - } + impl spanned: Serializable { + fn serialize(s: &S) { + do s.emit_rec { + s.emit_field("node", 0, || self.node.serialize(s)); + s.emit_field("span", 1, || self.span.serialize(s)); + } + } } -In general, the code to serialize an instance `v` of a non-built-in -type a::b::c looks like: - - a::b::serialize_c(s, {|v| c_T0}, ..., {|v| c_Tn}, v) - -where `c_Ti` is the code to serialize an instance `v` of the type -`Ti`. - -Similarly, the code to deserialize an instance of a non-built-in type -`a::b::c` using the deserializer `d` looks like: - - a::b::deserialize_c(d, {|| c_T0}, ..., {|| c_Tn}) - -where `c_Ti` is the code to deserialize an instance of `Ti` using the -deserializer `d`. + impl spanned: Deserializable { + static fn deserialize(d: &D) -> spanned { + do d.read_rec { + { + node: d.read_field(~"node", 0, || deserialize(d)), + span: d.read_field(~"span", 1, || deserialize(d)), + } + } + } + } FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the standard library. @@ -69,788 +71,1035 @@ into the tree. This is intended to prevent us from inserting the same node twice. */ + use base::*; use codemap::span; use std::map; use std::map::HashMap; -export expand; +export expand_auto_serialize; +export expand_auto_deserialize; // Transitional reexports so qquote can find the paths it is looking for mod syntax { - #[legacy_exports]; pub use ext; pub use parse; } -type ser_tps_map = map::HashMap ~[@ast::stmt]>; -type deser_tps_map = map::HashMap @ast::expr>; - -fn expand(cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item]) -> ~[@ast::item] { - fn not_auto_serialize(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) != ~"auto_serialize" +fn expand_auto_serialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_serialize(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_serialize" } fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, not_auto_serialize), + @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize(a)), .. *item} } - do vec::flat_map(in_items) |in_item| { - match in_item.node { - ast::item_ty(ty, tps) => { - vec::append(~[filter_attrs(*in_item)], - ty_fns(cx, in_item.ident, ty, tps)) - } + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_serialize) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let ser_impl = mk_rec_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); - ast::item_enum(enum_definition, tps) => { - vec::append(~[filter_attrs(*in_item)], - enum_fns(cx, in_item.ident, - in_item.span, enum_definition.variants, tps)) - } + ~[filter_attrs(*item), ser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let ser_impl = mk_struct_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); - _ => { - cx.span_err(span, ~"#[auto_serialize] can only be \ - applied to type and enum \ - definitions"); - ~[*in_item] - } + ~[filter_attrs(*item), ser_impl] + }, + ast::item_enum(enum_def, tps) => { + let ser_impl = mk_enum_ser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_serialize] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] + } + } +} + +fn expand_auto_deserialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_deserialize(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_deserialize" + } + + fn filter_attrs(item: @ast::item) -> @ast::item { + @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize(a)), + .. *item} + } + + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_deserialize) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let deser_impl = mk_rec_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let deser_impl = mk_struct_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_enum(enum_def, tps) => { + let deser_impl = mk_enum_deser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_deserialize] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] } } } priv impl ext_ctxt { - fn helper_path(base_path: @ast::path, - helper_name: ~str) -> @ast::path { - let head = vec::init(base_path.idents); - let tail = vec::last(base_path.idents); - self.path(base_path.span, - vec::append(head, - ~[self.parse_sess().interner. - intern(@(helper_name + ~"_" + - *self.parse_sess().interner.get( - tail)))])) + fn expr(span: span, node: ast::expr_) -> @ast::expr { + @{id: self.next_id(), callee_id: self.next_id(), + node: node, span: span} } - fn ty_fn(span: span, - -input_tys: ~[@ast::ty], - -output: @ast::ty) -> @ast::ty { - let args = do vec::map(input_tys) |ty| { - {mode: ast::expl(ast::by_ref), - ty: *ty, - ident: parse::token::special_idents::invalid, - id: self.next_id()} - }; + fn path(span: span, strs: ~[ast::ident]) -> @ast::path { + @{span: span, global: false, idents: strs, rp: None, types: ~[]} + } + fn path_tps(span: span, strs: ~[ast::ident], + tps: ~[@ast::ty]) -> @ast::path { + @{span: span, global: false, idents: strs, rp: None, types: tps} + } + + fn ty_path(span: span, strs: ~[ast::ident], + tps: ~[@ast::ty]) -> @ast::ty { @{id: self.next_id(), - node: ast::ty_fn(ast::proto_block, - ast::impure_fn, - @~[], - {inputs: args, - output: output, - cf: ast::return_val}), + node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), span: span} } - fn ty_nil(span: span) -> @ast::ty { - @{id: self.next_id(), node: ast::ty_nil, span: span} + fn binder_pat(span: span, nm: ast::ident) -> @ast::pat { + let path = @{span: span, global: false, idents: ~[nm], + rp: None, types: ~[]}; + @{id: self.next_id(), + node: ast::pat_ident(ast::bind_by_implicit_ref, + path, + None), + span: span} } - fn var_ref(span: span, name: ast::ident) -> @ast::expr { - self.expr(span, ast::expr_path(self.path(span, ~[name]))) + fn stmt(expr: @ast::expr) -> @ast::stmt { + @{node: ast::stmt_semi(expr, self.next_id()), + span: expr.span} } - fn alt_stmt(arms: ~[ast::arm], - span: span, -v: @ast::expr) -> @ast::stmt { - self.stmt( - self.expr( - span, - ast::expr_match(v, arms))) + fn lit_str(span: span, s: @~str) -> @ast::expr { + self.expr( + span, + ast::expr_vstore( + self.expr( + span, + ast::expr_lit( + @{node: ast::lit_str(s), + span: span})), + ast::expr_vstore_uniq)) } - fn clone_folder() -> fold::ast_fold { - fold::make_fold(@{ - new_id: |_id| self.next_id(), - .. *fold::default_ast_fold() - }) + fn lit_uint(span: span, i: uint) -> @ast::expr { + self.expr( + span, + ast::expr_lit( + @{node: ast::lit_uint(i as u64, ast::ty_u), + span: span})) } - fn clone(v: @ast::expr) -> @ast::expr { - let fld = self.clone_folder(); - fld.fold_expr(v) + fn lambda(blk: ast::blk) -> @ast::expr { + let ext_cx = self; + let blk_e = self.expr(blk.span, ast::expr_block(blk)); + #ast{ || $(blk_e) } } - fn clone_ty(v: @ast::ty) -> @ast::ty { - let fld = self.clone_folder(); - fld.fold_ty(v) + fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk { + {node: {view_items: ~[], + stmts: stmts, + expr: None, + id: self.next_id(), + rules: ast::default_blk}, + span: span} } - fn clone_ty_param(v: ast::ty_param) -> ast::ty_param { - let fld = self.clone_folder(); - fold::fold_ty_param(v, fld) + fn expr_blk(expr: @ast::expr) -> ast::blk { + {node: {view_items: ~[], + stmts: ~[], + expr: Some(expr), + id: self.next_id(), + rules: ast::default_blk}, + span: expr.span} } - fn at(span: span, expr: @ast::expr) -> @ast::expr { - fn repl_sp(old_span: span, repl_span: span, with_span: span) -> span { - if old_span == repl_span { - with_span - } else { - old_span - } - } + fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr { + self.expr(span, ast::expr_path(self.path(span, strs))) + } - let fld = fold::make_fold(@{ - new_span: |a| repl_sp(a, ast_util::dummy_sp(), span), - .. *fold::default_ast_fold() + fn expr_var(span: span, var: ~str) -> @ast::expr { + self.expr_path(span, ~[self.ident_of(var)]) + } + + fn expr_field( + span: span, + expr: @ast::expr, + ident: ast::ident + ) -> @ast::expr { + self.expr(span, ast::expr_field(expr, ident, ~[])) + } + + fn expr_call( + span: span, + expr: @ast::expr, + args: ~[@ast::expr] + ) -> @ast::expr { + self.expr(span, ast::expr_call(expr, args, false)) + } + + fn lambda_expr(expr: @ast::expr) -> @ast::expr { + self.lambda(self.expr_blk(expr)) + } + + fn lambda_stmts(span: span, stmts: ~[@ast::stmt]) -> @ast::expr { + self.lambda(self.blk(span, stmts)) + } +} + +fn mk_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + path: @ast::path, + tps: ~[ast::ty_param], + f: fn(@ast::ty) -> @ast::method +) -> @ast::item { + // All the type parameters need to bound to the trait. + let trait_tps = do tps.map |tp| { + let t_bound = ast::bound_trait(@{ + id: cx.next_id(), + node: ast::ty_path(path, cx.next_id()), + span: span, }); - fld.fold_expr(expr) - } -} - -fn ser_path(cx: ext_ctxt, tps: ser_tps_map, path: @ast::path, - -s: @ast::expr, -v: @ast::expr) - -> ~[@ast::stmt] { - let ext_cx = cx; // required for #ast{} - - // We want to take a path like a::b::c<...> and generate a call - // like a::b::c::serialize(s, ...), as described above. - - let callee = - cx.expr( - path.span, - ast::expr_path( - cx.helper_path(path, ~"serialize"))); - - let ty_args = do vec::map(path.types) |ty| { - let sv_stmts = ser_ty(cx, tps, *ty, cx.clone(s), #ast{ __v }); - let sv = cx.expr(path.span, - ast::expr_block(cx.blk(path.span, sv_stmts))); - cx.at(ty.span, #ast{ |__v| $(sv) }) - }; - - ~[cx.stmt( - cx.expr( - path.span, - ast::expr_call(callee, vec::append(~[s, v], ty_args), false)))] -} - -fn ser_variant(cx: ext_ctxt, - tps: ser_tps_map, - tys: ~[@ast::ty], - span: span, - -s: @ast::expr, - pfn: fn(~[@ast::pat]) -> ast::pat_, - bodyfn: fn(-v: @ast::expr, ast::blk) -> @ast::expr, - argfn: fn(-v: @ast::expr, uint, ast::blk) -> @ast::expr) - -> ast::arm { - let vnames = do vec::from_fn(vec::len(tys)) |i| { - cx.parse_sess().interner.intern(@fmt!("__v%u", i)) - }; - let pats = do vec::from_fn(vec::len(tys)) |i| { - cx.binder_pat(tys[i].span, vnames[i]) - }; - let pat: @ast::pat = @{id: cx.next_id(), node: pfn(pats), span: span}; - let stmts = do vec::from_fn(vec::len(tys)) |i| { - let v = cx.var_ref(span, vnames[i]); - let arg_blk = - cx.blk( - span, - ser_ty(cx, tps, tys[i], cx.clone(s), move v)); - cx.stmt(argfn(cx.clone(s), i, arg_blk)) - }; - - let body_blk = cx.blk(span, stmts); - let body = cx.blk(span, ~[cx.stmt(bodyfn(move s, body_blk))]); - - {pats: ~[pat], guard: None, body: body} -} - -fn ser_lambda(cx: ext_ctxt, tps: ser_tps_map, ty: @ast::ty, - -s: @ast::expr, -v: @ast::expr) -> @ast::expr { - cx.lambda(cx.blk(ty.span, ser_ty(cx, tps, ty, move s, move v))) -} - -fn is_vec_or_str(ty: @ast::ty) -> bool { - match ty.node { - ast::ty_vec(_) => true, - // This may be wrong if the user has shadowed (!) str - ast::ty_path(@{span: _, global: _, idents: ids, - rp: None, types: _}, _) - if ids == ~[parse::token::special_idents::str] => true, - _ => false - } -} - -fn ser_ty(cx: ext_ctxt, tps: ser_tps_map, - ty: @ast::ty, -s: @ast::expr, -v: @ast::expr) - -> ~[@ast::stmt] { - - let ext_cx = cx; // required for #ast{} - - match ty.node { - ast::ty_nil => { - ~[#ast[stmt]{$(s).emit_nil()}] - } - - ast::ty_bot => { - cx.span_err( - ty.span, fmt!("Cannot serialize bottom type")); - ~[] - } - - ast::ty_box(mt) => { - let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) }); - ~[#ast[stmt]{$(s).emit_box($(l));}] - } - - // For unique evecs/estrs, just pass through to underlying vec or str - ast::ty_uniq(mt) if is_vec_or_str(mt.ty) => { - ser_ty(cx, tps, mt.ty, move s, move v) - } - - ast::ty_uniq(mt) => { - let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) }); - ~[#ast[stmt]{$(s).emit_uniq($(l));}] - } - - ast::ty_ptr(_) | ast::ty_rptr(_, _) => { - cx.span_err(ty.span, ~"cannot serialize pointer types"); - ~[] - } - - ast::ty_rec(flds) => { - let fld_stmts = do vec::from_fn(vec::len(flds)) |fidx| { - let fld = flds[fidx]; - let vf = cx.expr(fld.span, - ast::expr_field(cx.clone(v), - fld.node.ident, - ~[])); - let s = cx.clone(s); - let f = cx.lit_str(fld.span, cx.parse_sess().interner.get( - fld.node.ident)); - let i = cx.lit_uint(fld.span, fidx); - let l = ser_lambda(cx, tps, fld.node.mt.ty, cx.clone(s), move vf); - #ast[stmt]{$(s).emit_rec_field($(f), $(i), $(l));} - }; - let fld_lambda = cx.lambda(cx.blk(ty.span, fld_stmts)); - ~[#ast[stmt]{$(s).emit_rec($(fld_lambda));}] - } - - ast::ty_fn(*) => { - cx.span_err(ty.span, ~"cannot serialize function types"); - ~[] - } - - ast::ty_tup(tys) => { - // Generate code like - // - // match v { - // (v1, v2, v3) { - // .. serialize v1, v2, v3 .. - // } - // }; - - let arms = ~[ - ser_variant( - - cx, tps, tys, ty.span, move s, - - // Generate pattern (v1, v2, v3) - |pats| ast::pat_tup(pats), - - // Generate body s.emit_tup(3, {|| blk }) - |-s, blk| { - let sz = cx.lit_uint(ty.span, vec::len(tys)); - let body = cx.lambda(blk); - #ast{ $(s).emit_tup($(sz), $(body)) } - }, - - // Generate s.emit_tup_elt(i, {|| blk }) - |-s, i, blk| { - let idx = cx.lit_uint(ty.span, i); - let body = cx.lambda(blk); - #ast{ $(s).emit_tup_elt($(idx), $(body)) } - }) - ]; - ~[cx.alt_stmt(arms, ty.span, move v)] - } - - ast::ty_path(path, _) => { - if path.idents.len() == 1 && path.types.is_empty() { - let ident = path.idents[0]; - - match tps.find(ident) { - Some(f) => f(v), - None => ser_path(cx, tps, path, move s, move v) - } - } else { - ser_path(cx, tps, path, move s, move v) + { + ident: tp.ident, + id: cx.next_id(), + bounds: @vec::append(~[t_bound], *tp.bounds) } - } - - ast::ty_mac(_) => { - cx.span_err(ty.span, ~"cannot serialize macro types"); - ~[] - } - - ast::ty_infer => { - cx.span_err(ty.span, ~"cannot serialize inferred types"); - ~[] - } - - ast::ty_vec(mt) => { - let ser_e = - cx.expr( - ty.span, - ast::expr_block( - cx.blk( - ty.span, - ser_ty( - cx, tps, mt.ty, - cx.clone(s), - cx.at(ty.span, #ast{ __e }))))); - - ~[#ast[stmt]{ - std::serialization::emit_from_vec($(s), $(v), |__e| $(ser_e)) - }] - } - - ast::ty_fixed_length(_, _) => { - cx.span_unimpl(ty.span, ~"serialization for fixed length types"); - } - } -} - -fn mk_ser_fn(cx: ext_ctxt, span: span, name: ast::ident, - tps: ~[ast::ty_param], - f: fn(ext_ctxt, ser_tps_map, - -v: @ast::expr, -v: @ast::expr) -> ~[@ast::stmt]) - -> @ast::item { - let ext_cx = cx; // required for #ast - - let tp_types = vec::map(tps, |tp| cx.ty_path(span, ~[tp.ident], ~[])); - let v_ty = cx.ty_path(span, ~[name], tp_types); - - let tp_inputs = - vec::map(tps, |tp| - {mode: ast::expl(ast::by_ref), - ty: cx.ty_fn(span, - ~[cx.ty_path(span, ~[tp.ident], ~[])], - cx.ty_nil(span)), - ident: cx.ident_of(~"__s" + cx.str_of(tp.ident)), - id: cx.next_id()}); - - debug!("tp_inputs = %?", tp_inputs); - - - let ser_inputs: ~[ast::arg] = - vec::append(~[{mode: ast::expl(ast::by_ref), - ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), - ident: cx.ident_of(~"__s"), - id: cx.next_id()}, - {mode: ast::expl(ast::by_ref), - ty: v_ty, - ident: cx.ident_of(~"__v"), - id: cx.next_id()}], - tp_inputs); - - let tps_map = map::HashMap(); - for vec::each2(tps, tp_inputs) |tp, arg| { - let arg_ident = arg.ident; - tps_map.insert( - tp.ident, - fn@(v: @ast::expr) -> ~[@ast::stmt] { - let f = cx.var_ref(span, arg_ident); - debug!("serializing type arg %s", cx.str_of(arg_ident)); - ~[#ast[stmt]{$(f)($(v));}] - }); - } - - let ser_bnds = @~[ - ast::bound_trait(cx.ty_path(span, - ~[cx.ident_of(~"std"), - cx.ident_of(~"serialization"), - cx.ident_of(~"Serializer")], - ~[]))]; - - let ser_tps: ~[ast::ty_param] = - vec::append(~[{ident: cx.ident_of(~"__S"), - id: cx.next_id(), - bounds: ser_bnds}], - vec::map(tps, |tp| cx.clone_ty_param(*tp))); - - let ser_output: @ast::ty = @{id: cx.next_id(), - node: ast::ty_nil, - span: span}; - - let ser_blk = cx.blk(span, - f(cx, tps_map, #ast{ __s }, #ast{ __v })); - - @{ident: cx.ident_of(~"serialize_" + cx.str_of(name)), - attrs: ~[], - id: cx.next_id(), - node: ast::item_fn({inputs: ser_inputs, - output: ser_output, - cf: ast::return_val}, - ast::impure_fn, - ser_tps, - ser_blk), - vis: ast::public, - span: span} -} - -// ______________________________________________________________________ - -fn deser_path(cx: ext_ctxt, tps: deser_tps_map, path: @ast::path, - -d: @ast::expr) -> @ast::expr { - // We want to take a path like a::b::c<...> and generate a call - // like a::b::c::deserialize(d, ...), as described above. - - let callee = - cx.expr( - path.span, - ast::expr_path( - cx.helper_path(path, ~"deserialize"))); - - let ty_args = do vec::map(path.types) |ty| { - let dv_expr = deser_ty(cx, tps, *ty, cx.clone(d)); - cx.lambda(cx.expr_blk(dv_expr)) }; - cx.expr(path.span, ast::expr_call(callee, vec::append(~[d], ty_args), - false)) + let opt_trait = Some(@{ + path: path, + ref_id: cx.next_id(), + impl_id: cx.next_id(), + }); + + let ty = cx.ty_path( + span, + ~[ident], + tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) + ); + + @{ + // This is a new-style impl declaration. + // XXX: clownshoes + ident: ast::token::special_idents::clownshoes_extensions, + attrs: ~[], + id: cx.next_id(), + node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), + vis: ast::public, + span: span, + } } -fn deser_lambda(cx: ext_ctxt, tps: deser_tps_map, ty: @ast::ty, - -d: @ast::expr) -> @ast::expr { - cx.lambda(cx.expr_blk(deser_ty(cx, tps, ty, move d))) +fn mk_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization::Serializable trait. + let path = cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Serializable"), + ] + ); + + mk_impl( + cx, + span, + ident, + path, + tps, + |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) + ) } -fn deser_ty(cx: ext_ctxt, tps: deser_tps_map, - ty: @ast::ty, -d: @ast::expr) -> @ast::expr { +fn mk_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization::Deserializable trait. + let path = cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Deserializable"), + ] + ); - let ext_cx = cx; // required for #ast{} + mk_impl( + cx, + span, + ident, + path, + tps, + |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) + ) +} - match ty.node { - ast::ty_nil => { - #ast{ $(d).read_nil() } - } +fn mk_ser_method( + cx: ext_ctxt, + span: span, + ser_body: ast::blk +) -> @ast::method { + let ser_bound = cx.ty_path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Serializer"), + ], + ~[] + ); - ast::ty_bot => { - #ast{ fail } - } + let ser_tps = ~[{ + ident: cx.ident_of(~"__S"), + id: cx.next_id(), + bounds: @~[ast::bound_trait(ser_bound)], + }]; - ast::ty_box(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ @$(d).read_box($(l)) } - } - - // For unique evecs/estrs, just pass through to underlying vec or str - ast::ty_uniq(mt) if is_vec_or_str(mt.ty) => { - deser_ty(cx, tps, mt.ty, move d) - } - - ast::ty_uniq(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ ~$(d).read_uniq($(l)) } - } - - ast::ty_ptr(_) | ast::ty_rptr(_, _) => { - #ast{ fail } - } - - ast::ty_rec(flds) => { - let fields = do vec::from_fn(vec::len(flds)) |fidx| { - let fld = flds[fidx]; - let d = cx.clone(d); - let f = cx.lit_str(fld.span, @cx.str_of(fld.node.ident)); - let i = cx.lit_uint(fld.span, fidx); - let l = deser_lambda(cx, tps, fld.node.mt.ty, cx.clone(d)); - {node: {mutbl: fld.node.mt.mutbl, - ident: fld.node.ident, - expr: #ast{ $(d).read_rec_field($(f), $(i), $(l))} }, - span: fld.span} - }; - let fld_expr = cx.expr(ty.span, ast::expr_rec(fields, None)); - let fld_lambda = cx.lambda(cx.expr_blk(fld_expr)); - #ast{ $(d).read_rec($(fld_lambda)) } - } - - ast::ty_fn(*) => { - #ast{ fail } - } - - ast::ty_tup(tys) => { - // Generate code like - // - // d.read_tup(3u) {|| - // (d.read_tup_elt(0u, {||...}), - // d.read_tup_elt(1u, {||...}), - // d.read_tup_elt(2u, {||...})) - // } - - let arg_exprs = do vec::from_fn(vec::len(tys)) |i| { - let idx = cx.lit_uint(ty.span, i); - let body = deser_lambda(cx, tps, tys[i], cx.clone(d)); - #ast{ $(d).read_tup_elt($(idx), $(body)) } - }; - let body = - cx.lambda(cx.expr_blk( - cx.expr(ty.span, ast::expr_tup(arg_exprs)))); - let sz = cx.lit_uint(ty.span, vec::len(tys)); - #ast{ $(d).read_tup($(sz), $(body)) } - } - - ast::ty_path(path, _) => { - if vec::len(path.idents) == 1u && - vec::is_empty(path.types) { - let ident = path.idents[0]; - - match tps.find(ident) { - Some(f) => f(), - None => deser_path(cx, tps, path, move d) + let ty_s = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), + mutbl: ast::m_imm } - } else { - deser_path(cx, tps, path, move d) - } - } + ), + span: span, + }; - ast::ty_mac(_) => { - #ast{ fail } - } + let ser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_s, + ident: cx.ident_of(~"__s"), + id: cx.next_id(), + }]; - ast::ty_infer => { - #ast{ fail } - } + let ser_output = @{ + id: cx.next_id(), + node: ast::ty_nil, + span: span, + }; - ast::ty_vec(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ std::serialization::read_to_vec($(d), $(l)) } - } + let ser_decl = { + inputs: ser_inputs, + output: ser_output, + cf: ast::return_val, + }; - ast::ty_fixed_length(_, _) => { - cx.span_unimpl(ty.span, ~"deserialization for fixed length types"); - } + @{ + ident: cx.ident_of(~"serialize"), + attrs: ~[], + tps: ser_tps, + self_ty: { node: ast::sty_region(ast::m_imm), span: span }, + purity: ast::impure_fn, + decl: ser_decl, + body: ser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, } } -fn mk_deser_fn(cx: ext_ctxt, span: span, - name: ast::ident, tps: ~[ast::ty_param], - f: fn(ext_ctxt, deser_tps_map, -v: @ast::expr) -> @ast::expr) - -> @ast::item { - let ext_cx = cx; // required for #ast +fn mk_deser_method( + cx: ext_ctxt, + span: span, + ty: @ast::ty, + deser_body: ast::blk +) -> @ast::method { + let deser_bound = cx.ty_path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Deserializer"), + ], + ~[] + ); - let tp_types = vec::map(tps, |tp| cx.ty_path(span, ~[tp.ident], ~[])); - let v_ty = cx.ty_path(span, ~[name], tp_types); + let deser_tps = ~[{ + ident: cx.ident_of(~"__D"), + id: cx.next_id(), + bounds: @~[ast::bound_trait(deser_bound)], + }]; - let tp_inputs = - vec::map(tps, |tp| - {mode: ast::expl(ast::by_ref), - ty: cx.ty_fn(span, - ~[], - cx.ty_path(span, ~[tp.ident], ~[])), - ident: cx.ident_of(~"__d" + cx.str_of(tp.ident)), - id: cx.next_id()}); + let ty_d = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), + mutbl: ast::m_imm + } + ), + span: span, + }; - debug!("tp_inputs = %?", tp_inputs); + let deser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_d, + ident: cx.ident_of(~"__d"), + id: cx.next_id(), + }]; - let deser_inputs: ~[ast::arg] = - vec::append(~[{mode: ast::expl(ast::by_ref), - ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), - ident: cx.ident_of(~"__d"), - id: cx.next_id()}], - tp_inputs); + let deser_decl = { + inputs: deser_inputs, + output: ty, + cf: ast::return_val, + }; - let tps_map = map::HashMap(); - for vec::each2(tps, tp_inputs) |tp, arg| { - let arg_ident = arg.ident; - tps_map.insert( - tp.ident, - fn@() -> @ast::expr { - let f = cx.var_ref(span, arg_ident); - #ast{ $(f)() } - }); + @{ + ident: cx.ident_of(~"deserialize"), + attrs: ~[], + tps: deser_tps, + self_ty: { node: ast::sty_static, span: span }, + purity: ast::impure_fn, + decl: deser_decl, + body: deser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, } +} - let deser_bnds = @~[ - ast::bound_trait(cx.ty_path( +fn mk_rec_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `__s.emit_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( span, - ~[cx.ident_of(~"std"), cx.ident_of(~"serialization"), - cx.ident_of(~"Deserializer")], - ~[]))]; + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_rec") + ), + ~[cx.lambda_stmts(span, fields)] + ); - let deser_tps: ~[ast::ty_param] = - vec::append(~[{ident: cx.ident_of(~"__D"), - id: cx.next_id(), - bounds: deser_bnds}], - vec::map(tps, |tp| { - let cloned = cx.clone_ty_param(*tp); - {bounds: @(vec::append(*cloned.bounds, - ~[ast::bound_copy])), - .. cloned} - })); - - let deser_blk = cx.expr_blk(f(cx, tps_map, #ast[expr]{__d})); - - @{ident: cx.ident_of(~"deserialize_" + cx.str_of(name)), - attrs: ~[], - id: cx.next_id(), - node: ast::item_fn({inputs: deser_inputs, - output: v_ty, - cf: ast::return_val}, - ast::impure_fn, - deser_tps, - deser_blk), - vis: ast::public, - span: span} + mk_ser_impl(cx, span, ident, tps, body) } -fn ty_fns(cx: ext_ctxt, name: ast::ident, - ty: @ast::ty, tps: ~[ast::ty_param]) - -> ~[@ast::item] { +fn mk_rec_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); - let span = ty.span; - ~[ - mk_ser_fn(cx, span, name, tps, |a,b,c,d| ser_ty(a, b, ty, move c, - move d)), - mk_deser_fn(cx, span, name, tps, |a,b,c| deser_ty(a, b, ty, move c)) - ] + // ast for `read_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_rec") + ), + ~[ + cx.lambda_expr( + cx.expr( + span, + ast::expr_rec(fields, None) + ) + ) + ] + ); + + mk_deser_impl(cx, span, ident, tps, body) } -fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident, - e_span: span, variants: ~[ast::variant], - -s: @ast::expr, -v: @ast::expr) -> ~[@ast::stmt] { - let ext_cx = cx; - let arms = do vec::from_fn(vec::len(variants)) |vidx| { - let variant = variants[vidx]; - let v_span = variant.span; - let v_name = variant.node.name; +fn mk_struct_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); - match variant.node.kind { - ast::tuple_variant_kind(args) => { - let variant_tys = vec::map(args, |a| a.ty); + // ast for `__s.emit_struct($(name), || $(fields))` + let ser_body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_stmts(span, fields), + ] + ); - ser_variant( - cx, tps, variant_tys, v_span, cx.clone(s), + mk_ser_impl(cx, span, ident, tps, ser_body) +} - // Generate pattern var(v1, v2, v3) - |pats| { - if vec::is_empty(pats) { - ast::pat_ident(ast::bind_by_implicit_ref, - cx.path(v_span, ~[v_name]), - None) - } else { - ast::pat_enum(cx.path(v_span, ~[v_name]), - Some(pats)) - } - }, +fn mk_struct_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); - // Generate body s.emit_enum_variant("foo", 0u, - // 3u, {|| blk }) - |-s, blk| { - let v_name = cx.lit_str(v_span, @cx.str_of(v_name)); - let v_id = cx.lit_uint(v_span, vidx); - let sz = cx.lit_uint(v_span, vec::len(variant_tys)); - let body = cx.lambda(blk); - #ast[expr]{ - $(s).emit_enum_variant($(v_name), $(v_id), - $(sz), $(body)) - } - }, + // ast for `read_struct($(name), || $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_expr( + cx.expr( + span, + ast::expr_struct( + cx.path(span, ~[ident]), + fields, + None + ) + ) + ), + ] + ); - // Generate s.emit_enum_variant_arg(i, {|| blk }) - |-s, i, blk| { - let idx = cx.lit_uint(v_span, i); - let body = cx.lambda(blk); - #ast[expr]{ - $(s).emit_enum_variant_arg($(idx), $(body)) - } - }) - } - _ => - fail ~"struct variants unimplemented for auto serialize" + mk_deser_impl(cx, span, ident, tps, body) +} + +// Records and structs don't have the same fields types, but they share enough +// that if we extract the right subfields out we can share the serialization +// generator code. +type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; + +fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { + do fields.map |field| { + { + span: field.span, + ident: field.node.ident, + mutbl: field.node.mt.mutbl, } - }; - let lam = cx.lambda(cx.blk(e_span, ~[cx.alt_stmt(arms, e_span, move v)])); - let e_name = cx.lit_str(e_span, @cx.str_of(e_name)); - ~[#ast[stmt]{ $(s).emit_enum($(e_name), $(lam)) }] + } } -fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: ast::ident, - e_span: span, variants: ~[ast::variant], - -d: @ast::expr) -> @ast::expr { - let ext_cx = cx; - let mut arms: ~[ast::arm] = do vec::from_fn(vec::len(variants)) |vidx| { - let variant = variants[vidx]; - let v_span = variant.span; - let v_name = variant.node.name; +fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { + do fields.map |field| { + let (ident, mutbl) = match field.node.kind { + ast::named_field(ident, mutbl, _) => (ident, mutbl), + _ => fail ~"[auto_serialize] does not support \ + unnamed fields", + }; - let body; + { + span: field.span, + ident: ident, + mutbl: match mutbl { + ast::class_mutable => ast::m_mutbl, + ast::class_immutable => ast::m_imm, + }, + } + } +} + +fn mk_ser_fields( + cx: ext_ctxt, + span: span, + fields: ~[field] +) -> ~[@ast::stmt] { + do fields.mapi |idx, field| { + // ast for `|| self.$(name).serialize(__s)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"self"), + field.ident + ), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` + cx.stmt( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ) + ) + } +} + +fn mk_deser_fields( + cx: ext_ctxt, + span: span, + fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] +) -> ~[ast::field] { + do fields.mapi |idx, field| { + // ast for `|| std::serialization::deserialize(__d)` + let expr_lambda = cx.lambda( + cx.expr_blk( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ) + ); + + // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` + let expr: @ast::expr = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ); + + { + node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, + span: span, + } + } +} + +fn mk_enum_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_ser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_ser_impl(cx, span, ident, tps, body) +} + +fn mk_enum_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_deser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_deser_impl(cx, span, ident, tps, body) +} + +fn ser_variant( + cx: ext_ctxt, + span: span, + v_name: ast::ident, + v_idx: uint, + args: ~[ast::variant_arg] +) -> ast::arm { + // Name the variant arguments. + let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); + + // Bind the names to the variant argument type. + let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); + + let pat_node = if pats.is_empty() { + ast::pat_ident( + ast::bind_by_implicit_ref, + cx.path(span, ~[v_name]), + None + ) + } else { + ast::pat_enum( + cx.path(span, ~[v_name]), + Some(pats) + ) + }; + + let pat = @{ + id: cx.next_id(), + node: pat_node, + span: span, + }; + + let stmts = do args.mapi |a_idx, _arg| { + // ast for `__s.emit_enum_variant_arg` + let expr_emit = cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant_arg") + ); + + // ast for `|| $(v).serialize(__s)` + let expr_serialize = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_path(span, ~[names[a_idx]]), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` + cx.stmt( + cx.expr_call( + span, + expr_emit, + ~[cx.lit_uint(span, a_idx), expr_serialize] + ) + ) + }; + + // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant") + ), + ~[ + cx.lit_str(span, @cx.str_of(v_name)), + cx.lit_uint(span, v_idx), + cx.lit_uint(span, stmts.len()), + cx.lambda_stmts(span, stmts), + ] + ); + + { pats: ~[pat], guard: None, body: cx.expr_blk(body) } +} + +fn mk_enum_ser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let arms = do variants.mapi |v_idx, variant| { match variant.node.kind { - ast::tuple_variant_kind(args) => { - let tys = vec::map(args, |a| a.ty); - - let arg_exprs = do vec::from_fn(vec::len(tys)) |i| { - let idx = cx.lit_uint(v_span, i); - let body = deser_lambda(cx, tps, tys[i], cx.clone(d)); - #ast{ $(d).read_enum_variant_arg($(idx), $(body)) } - }; - - body = { - if vec::is_empty(tys) { - // for a nullary variant v, do "v" - cx.var_ref(v_span, v_name) - } else { - // for an n-ary variant v, do "v(a_1, ..., a_n)" - cx.expr(v_span, ast::expr_call( - cx.var_ref(v_span, v_name), arg_exprs, false)) - } - }; - } + ast::tuple_variant_kind(args) => + ser_variant(cx, span, variant.node.name, v_idx, args), ast::struct_variant_kind(*) => fail ~"struct variants unimplemented", ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented" + fail ~"enum variants unimplemented", } - - {pats: ~[@{id: cx.next_id(), - node: ast::pat_lit(cx.lit_uint(v_span, vidx)), - span: v_span}], - guard: None, - body: cx.expr_blk(body)} }; - let impossible_case = {pats: ~[@{id: cx.next_id(), - node: ast::pat_wild, - span: e_span}], - guard: None, - // FIXME #3198: proper error message - body: cx.expr_blk(cx.expr(e_span, - ast::expr_fail(None)))}; - arms += ~[impossible_case]; + // ast for `match *self { $(arms) }` + let match_expr = cx.expr( + span, + ast::expr_match( + cx.expr( + span, + ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) + ), + arms + ) + ); - // Generate code like: - let e_name = cx.lit_str(e_span, @cx.str_of(e_name)); - let alt_expr = cx.expr(e_span, - ast::expr_match(#ast{__i}, arms)); - let var_lambda = #ast{ |__i| $(alt_expr) }; - let read_var = #ast{ $(cx.clone(d)).read_enum_variant($(var_lambda)) }; - let read_lambda = cx.lambda(cx.expr_blk(read_var)); - #ast{ $(d).read_enum($(e_name), $(read_lambda)) } + // ast for `__s.emit_enum($(name), || $(match_expr))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + cx.lambda_expr(match_expr), + ] + ) } -fn enum_fns(cx: ext_ctxt, e_name: ast::ident, e_span: span, - variants: ~[ast::variant], tps: ~[ast::ty_param]) - -> ~[@ast::item] { - ~[ - mk_ser_fn(cx, e_span, e_name, tps, - |a,b,c,d| ser_enum(a, b, e_name, e_span, variants, move c, - move d)), - mk_deser_fn(cx, e_span, e_name, tps, - |a,b,c| deser_enum(a, b, e_name, e_span, variants, move c)) - ] +fn mk_enum_deser_variant_nary( + cx: ext_ctxt, + span: span, + name: ast::ident, + args: ~[ast::variant_arg] +) -> @ast::expr { + let args = do args.mapi |idx, _arg| { + // ast for `|| std::serialization::deserialize(__d)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ); + + // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant_arg") + ), + ~[cx.lit_uint(span, idx), expr_lambda] + ) + }; + + // ast for `$(name)($(args))` + cx.expr_call(span, cx.expr_path(span, ~[name]), args) +} + +fn mk_enum_deser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let mut arms = do variants.mapi |v_idx, variant| { + let body = match variant.node.kind { + ast::tuple_variant_kind(args) => { + if args.is_empty() { + // for a nullary variant v, do "v" + cx.expr_path(span, ~[variant.node.name]) + } else { + // for an n-ary variant v, do "v(a_1, ..., a_n)" + mk_enum_deser_variant_nary( + cx, + span, + variant.node.name, + args + ) + } + }, + ast::struct_variant_kind(*) => + fail ~"struct variants unimplemented", + ast::enum_variant_kind(*) => + fail ~"enum variants unimplemented", + }; + + let pat = @{ + id: cx.next_id(), + node: ast::pat_lit(cx.lit_uint(span, v_idx)), + span: span, + }; + + { + pats: ~[pat], + guard: None, + body: cx.expr_blk(body), + } + }; + + let impossible_case = { + pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], + guard: None, + + // FIXME(#3198): proper error message + body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), + }; + + arms.push(impossible_case); + + // ast for `|i| { match i { $(arms) } }` + let expr_lambda = cx.expr( + span, + ast::expr_fn_block( + { + inputs: ~[{ + mode: ast::infer(cx.next_id()), + ty: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span + }, + ident: cx.ident_of(~"i"), + id: cx.next_id(), + }], + output: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span, + }, + cf: ast::return_val, + }, + cx.expr_blk( + cx.expr( + span, + ast::expr_match(cx.expr_var(span, ~"i"), arms) + ) + ), + @~[] + ) + ); + + // ast for `__d.read_enum_variant($(expr_lambda))` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant") + ), + ~[expr_lambda] + ) + ); + + // ast for `__d.read_enum($(e_name), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + expr_lambda + ] + ) } diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs index ba48b0d3f5fa..b3102f8b4f72 100644 --- a/src/libsyntax/ext/auto_serialize2.rs +++ b/src/libsyntax/ext/auto_serialize2.rs @@ -214,120 +214,6 @@ fn expand_auto_deserialize( } } -priv impl ext_ctxt { - fn expr(span: span, node: ast::expr_) -> @ast::expr { - @{id: self.next_id(), callee_id: self.next_id(), - node: node, span: span} - } - - fn path(span: span, strs: ~[ast::ident]) -> @ast::path { - @{span: span, global: false, idents: strs, rp: None, types: ~[]} - } - - fn path_tps(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::path { - @{span: span, global: false, idents: strs, rp: None, types: tps} - } - - fn ty_path(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::ty { - @{id: self.next_id(), - node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), - span: span} - } - - fn binder_pat(span: span, nm: ast::ident) -> @ast::pat { - let path = @{span: span, global: false, idents: ~[nm], - rp: None, types: ~[]}; - @{id: self.next_id(), - node: ast::pat_ident(ast::bind_by_implicit_ref, - path, - None), - span: span} - } - - fn stmt(expr: @ast::expr) -> @ast::stmt { - @{node: ast::stmt_semi(expr, self.next_id()), - span: expr.span} - } - - fn lit_str(span: span, s: @~str) -> @ast::expr { - self.expr( - span, - ast::expr_vstore( - self.expr( - span, - ast::expr_lit( - @{node: ast::lit_str(s), - span: span})), - ast::expr_vstore_uniq)) - } - - fn lit_uint(span: span, i: uint) -> @ast::expr { - self.expr( - span, - ast::expr_lit( - @{node: ast::lit_uint(i as u64, ast::ty_u), - span: span})) - } - - fn lambda(blk: ast::blk) -> @ast::expr { - let ext_cx = self; - let blk_e = self.expr(blk.span, ast::expr_block(blk)); - #ast{ || $(blk_e) } - } - - fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk { - {node: {view_items: ~[], - stmts: stmts, - expr: None, - id: self.next_id(), - rules: ast::default_blk}, - span: span} - } - - fn expr_blk(expr: @ast::expr) -> ast::blk { - {node: {view_items: ~[], - stmts: ~[], - expr: Some(expr), - id: self.next_id(), - rules: ast::default_blk}, - span: expr.span} - } - - fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr { - self.expr(span, ast::expr_path(self.path(span, strs))) - } - - fn expr_var(span: span, var: ~str) -> @ast::expr { - self.expr_path(span, ~[self.ident_of(var)]) - } - - fn expr_field( - span: span, - expr: @ast::expr, - ident: ast::ident - ) -> @ast::expr { - self.expr(span, ast::expr_field(expr, ident, ~[])) - } - - fn expr_call( - span: span, - expr: @ast::expr, - args: ~[@ast::expr] - ) -> @ast::expr { - self.expr(span, ast::expr_call(expr, args, false)) - } - - fn lambda_expr(expr: @ast::expr) -> @ast::expr { - self.lambda(self.expr_blk(expr)) - } - - fn lambda_stmts(span: span, stmts: ~[@ast::stmt]) -> @ast::expr { - self.lambda(self.blk(span, stmts)) - } -} - fn mk_impl( cx: ext_ctxt, span: span, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 794c5233e21e..ab56b6bb322e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -81,8 +81,6 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { builtin_item_tt( ext::tt::macro_rules::add_new_extension)); syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); - syntax_expanders.insert(~"auto_serialize", - item_decorator(ext::auto_serialize::expand)); syntax_expanders.insert( ~"auto_serialize2", item_decorator(ext::auto_serialize2::expand_auto_serialize)); @@ -143,16 +141,10 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); syntax_expanders.insert( ~"auto_serialize", - item_decorator(ext::auto_serialize2::expand_auto_serialize)); + item_decorator(ext::auto_serialize::expand_auto_serialize)); syntax_expanders.insert( ~"auto_deserialize", - item_decorator(ext::auto_serialize2::expand_auto_deserialize)); - syntax_expanders.insert( - ~"auto_serialize2", - item_decorator(ext::auto_serialize2::expand_auto_serialize)); - syntax_expanders.insert( - ~"auto_deserialize2", - item_decorator(ext::auto_serialize2::expand_auto_deserialize)); + item_decorator(ext::auto_serialize::expand_auto_deserialize)); syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext)); syntax_expanders.insert(~"concat_idents", builtin(ext::concat_idents::expand_syntax_ext)); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 19e79a4ae7a9..b63260997f75 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -2,6 +2,8 @@ use util::interner; use util::interner::interner; use std::map::HashMap; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum binop { @@ -17,6 +19,8 @@ enum binop { SHR, } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum token { @@ -75,6 +79,8 @@ enum token { EOF, } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] /// For interpolation during macro expansion. diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 4a6bac9cd64b..4c29fc5512a7 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -128,9 +128,9 @@ mod ext { mod ident_to_str; #[legacy_exports] mod log_syntax; - #[cfg(stage0)] #[legacy_exports] mod auto_serialize; + #[cfg(stage0)] #[legacy_exports] mod auto_serialize2; #[legacy_exports] diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 197e567ab2f8..6b8c995ffd26 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -1,8 +1,9 @@ // Decoding metadata from a single crate's metadata -use std::{ebml2, map}; +use std::ebml; +use std::map; use std::map::HashMap; -use std::serialization2::deserialize; +use std::serialization::deserialize; use io::WriterUtil; use dvec::DVec; use syntax::{ast, ast_util}; @@ -64,25 +65,25 @@ export translate_def_id; // what crate that's in and give us a def_id that makes sense for the current // build. -fn lookup_hash(d: ebml2::Doc, eq_fn: fn(x:&[u8]) -> bool, hash: uint) -> - Option { - let index = ebml2::get_doc(d, tag_index); - let table = ebml2::get_doc(index, tag_index_table); +fn lookup_hash(d: ebml::Doc, eq_fn: fn(x:&[u8]) -> bool, hash: uint) -> + Option { + let index = ebml::get_doc(d, tag_index); + let table = ebml::get_doc(index, tag_index_table); let hash_pos = table.start + hash % 256u * 4u; let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4u) as uint; - let tagged_doc = ebml2::doc_at(d.data, pos); + let tagged_doc = ebml::doc_at(d.data, pos); let belt = tag_index_buckets_bucket_elt; - for ebml2::tagged_docs(tagged_doc.doc, belt) |elt| { + for ebml::tagged_docs(tagged_doc.doc, belt) |elt| { let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4u) as uint; if eq_fn(vec::view(*elt.data, elt.start + 4u, elt.end)) { - return Some(ebml2::doc_at(d.data, pos).doc); + return Some(ebml::doc_at(d.data, pos).doc); } }; None } -fn maybe_find_item(item_id: int, items: ebml2::Doc) -> Option { +fn maybe_find_item(item_id: int, items: ebml::Doc) -> Option { fn eq_item(bytes: &[u8], item_id: int) -> bool { return io::u64_from_be_bytes(vec::view(bytes, 0u, 4u), 0u, 4u) as int == item_id; @@ -92,14 +93,14 @@ fn maybe_find_item(item_id: int, items: ebml2::Doc) -> Option { item_id.hash() as uint) } -fn find_item(item_id: int, items: ebml2::Doc) -> ebml2::Doc { +fn find_item(item_id: int, items: ebml::Doc) -> ebml::Doc { return maybe_find_item(item_id, items).get(); } -// Looks up an item in the given metadata and returns an ebml2 doc pointing +// Looks up an item in the given metadata and returns an ebml doc pointing // to the item data. -fn lookup_item(item_id: int, data: @~[u8]) -> ebml2::Doc { - let items = ebml2::get_doc(ebml2::Doc(data), tag_items); +fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc { + let items = ebml::get_doc(ebml::Doc(data), tag_items); match maybe_find_item(item_id, items) { None => fail(fmt!("lookup_item: id not found: %d", item_id)), Some(d) => d @@ -137,9 +138,9 @@ impl Family : cmp::Eq { pure fn ne(other: &Family) -> bool { !self.eq(other) } } -fn item_family(item: ebml2::Doc) -> Family { - let fam = ebml2::get_doc(item, tag_items_data_item_family); - match ebml2::doc_as_u8(fam) as char { +fn item_family(item: ebml::Doc) -> Family { + let fam = ebml::get_doc(item, tag_items_data_item_family); + match ebml::doc_as_u8(fam) as char { 'c' => Const, 'f' => Fn, 'u' => UnsafeFn, @@ -165,59 +166,59 @@ fn item_family(item: ebml2::Doc) -> Family { } } -fn item_symbol(item: ebml2::Doc) -> ~str { - let sym = ebml2::get_doc(item, tag_items_data_item_symbol); - return str::from_bytes(ebml2::doc_data(sym)); +fn item_symbol(item: ebml::Doc) -> ~str { + let sym = ebml::get_doc(item, tag_items_data_item_symbol); + return str::from_bytes(ebml::doc_data(sym)); } -fn item_parent_item(d: ebml2::Doc) -> Option { - for ebml2::tagged_docs(d, tag_items_data_parent_item) |did| { - return Some(ebml2::with_doc_data(did, |d| parse_def_id(d))); +fn item_parent_item(d: ebml::Doc) -> Option { + for ebml::tagged_docs(d, tag_items_data_parent_item) |did| { + return Some(ebml::with_doc_data(did, |d| parse_def_id(d))); } None } -fn item_def_id(d: ebml2::Doc, cdata: cmd) -> ast::def_id { - let tagdoc = ebml2::get_doc(d, tag_def_id); - return translate_def_id(cdata, ebml2::with_doc_data(tagdoc, +fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id { + let tagdoc = ebml::get_doc(d, tag_def_id); + return translate_def_id(cdata, ebml::with_doc_data(tagdoc, |d| parse_def_id(d))); } -fn each_reexport(d: ebml2::Doc, f: fn(ebml2::Doc) -> bool) { - for ebml2::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| { +fn each_reexport(d: ebml::Doc, f: fn(ebml::Doc) -> bool) { + for ebml::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| { if !f(reexport_doc) { return; } } } -fn field_mutability(d: ebml2::Doc) -> ast::class_mutability { +fn field_mutability(d: ebml::Doc) -> ast::class_mutability { // Use maybe_get_doc in case it's a method option::map_default( - &ebml2::maybe_get_doc(d, tag_class_mut), + &ebml::maybe_get_doc(d, tag_class_mut), ast::class_immutable, |d| { - match ebml2::doc_as_u8(*d) as char { + match ebml::doc_as_u8(*d) as char { 'm' => ast::class_mutable, _ => ast::class_immutable } }) } -fn variant_disr_val(d: ebml2::Doc) -> Option { - do option::chain(ebml2::maybe_get_doc(d, tag_disr_val)) |val_doc| { - int::parse_bytes(ebml2::doc_data(val_doc), 10u) +fn variant_disr_val(d: ebml::Doc) -> Option { + do option::chain(ebml::maybe_get_doc(d, tag_disr_val)) |val_doc| { + int::parse_bytes(ebml::doc_data(val_doc), 10u) } } -fn doc_type(doc: ebml2::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { - let tp = ebml2::get_doc(doc, tag_items_data_item_type); +fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { + let tp = ebml::get_doc(doc, tag_items_data_item_type); parse_ty_data(tp.data, cdata.cnum, tp.start, tcx, |did| { translate_def_id(cdata, did) }) } -fn item_type(item_id: ast::def_id, item: ebml2::Doc, +fn item_type(item_id: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { let t = doc_type(item, tcx, cdata); if family_names_type(item_family(item)) { @@ -225,18 +226,18 @@ fn item_type(item_id: ast::def_id, item: ebml2::Doc, } else { t } } -fn item_impl_traits(item: ebml2::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] { +fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] { let mut results = ~[]; - for ebml2::tagged_docs(item, tag_impl_trait) |ity| { + for ebml::tagged_docs(item, tag_impl_trait) |ity| { results.push(doc_type(ity, tcx, cdata)); }; results } -fn item_ty_param_bounds(item: ebml2::Doc, tcx: ty::ctxt, cdata: cmd) +fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> @~[ty::param_bounds] { let mut bounds = ~[]; - for ebml2::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| { + for ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| { let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx, |did| { translate_def_id(cdata, did) }); @@ -245,42 +246,42 @@ fn item_ty_param_bounds(item: ebml2::Doc, tcx: ty::ctxt, cdata: cmd) @bounds } -fn item_ty_region_param(item: ebml2::Doc) -> Option { - ebml2::maybe_get_doc(item, tag_region_param).map(|doc| { - deserialize(&ebml2::Deserializer(*doc)) +fn item_ty_region_param(item: ebml::Doc) -> Option { + ebml::maybe_get_doc(item, tag_region_param).map(|doc| { + deserialize(&ebml::Deserializer(*doc)) }) } -fn item_ty_param_count(item: ebml2::Doc) -> uint { +fn item_ty_param_count(item: ebml::Doc) -> uint { let mut n = 0u; - ebml2::tagged_docs(item, tag_items_data_item_ty_param_bounds, + ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds, |_p| { n += 1u; true } ); n } -fn enum_variant_ids(item: ebml2::Doc, cdata: cmd) -> ~[ast::def_id] { +fn enum_variant_ids(item: ebml::Doc, cdata: cmd) -> ~[ast::def_id] { let mut ids: ~[ast::def_id] = ~[]; let v = tag_items_data_item_variant; - for ebml2::tagged_docs(item, v) |p| { - let ext = ebml2::with_doc_data(p, |d| parse_def_id(d)); + for ebml::tagged_docs(item, v) |p| { + let ext = ebml::with_doc_data(p, |d| parse_def_id(d)); ids.push({crate: cdata.cnum, node: ext.node}); }; return ids; } -fn item_path(intr: @ident_interner, item_doc: ebml2::Doc) -> ast_map::path { - let path_doc = ebml2::get_doc(item_doc, tag_path); +fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path { + let path_doc = ebml::get_doc(item_doc, tag_path); - let len_doc = ebml2::get_doc(path_doc, tag_path_len); - let len = ebml2::doc_as_u32(len_doc) as uint; + let len_doc = ebml::get_doc(path_doc, tag_path_len); + let len = ebml::doc_as_u32(len_doc) as uint; let mut result = vec::with_capacity(len); - for ebml2::docs(path_doc) |tag, elt_doc| { + for ebml::docs(path_doc) |tag, elt_doc| { if tag == tag_path_elt_mod { - let str = ebml2::doc_as_str(elt_doc); + let str = ebml::doc_as_str(elt_doc); result.push(ast_map::path_mod(intr.intern(@str))); } else if tag == tag_path_elt_name { - let str = ebml2::doc_as_str(elt_doc); + let str = ebml::doc_as_str(elt_doc); result.push(ast_map::path_name(intr.intern(@str))); } else { // ignore tag_path_len element @@ -290,12 +291,12 @@ fn item_path(intr: @ident_interner, item_doc: ebml2::Doc) -> ast_map::path { return result; } -fn item_name(intr: @ident_interner, item: ebml2::Doc) -> ast::ident { - let name = ebml2::get_doc(item, tag_paths_data_name); - intr.intern(@str::from_bytes(ebml2::doc_data(name))) +fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident { + let name = ebml::get_doc(item, tag_paths_data_name); + intr.intern(@str::from_bytes(ebml::doc_data(name))) } -fn item_to_def_like(item: ebml2::Doc, did: ast::def_id, cnum: ast::crate_num) +fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) -> def_like { let fam = item_family(item); match fam { @@ -367,10 +368,10 @@ fn get_impl_traits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::t] { fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, name: ast::ident) -> ast::def_id { - let items = ebml2::get_doc(ebml2::Doc(cdata.data), tag_items); + let items = ebml::get_doc(ebml::Doc(cdata.data), tag_items); let mut found = None; - for ebml2::tagged_docs(find_item(id, items), tag_item_impl_method) |mid| { - let m_did = ebml2::with_doc_data(mid, |d| parse_def_id(d)); + for ebml::tagged_docs(find_item(id, items), tag_item_impl_method) |mid| { + let m_did = ebml::with_doc_data(mid, |d| parse_def_id(d)); if item_name(intr, find_item(m_did.node, items)) == name { found = Some(translate_def_id(cdata, m_did)); } @@ -380,14 +381,14 @@ fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, fn get_class_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, name: ast::ident) -> ast::def_id { - let items = ebml2::get_doc(ebml2::Doc(cdata.data), tag_items); + let items = ebml::get_doc(ebml::Doc(cdata.data), tag_items); let mut found = None; let cls_items = match maybe_find_item(id, items) { Some(it) => it, None => fail (fmt!("get_class_method: class id not found \ when looking up method %s", *intr.get(name))) }; - for ebml2::tagged_docs(cls_items, tag_item_trait_method) |mid| { + for ebml::tagged_docs(cls_items, tag_item_trait_method) |mid| { let m_did = item_def_id(mid, cdata); if item_name(intr, mid) == name { found = Some(m_did); @@ -401,16 +402,16 @@ fn get_class_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, } fn class_dtor(cdata: cmd, id: ast::node_id) -> Option { - let items = ebml2::get_doc(ebml2::Doc(cdata.data), tag_items); + let items = ebml::get_doc(ebml::Doc(cdata.data), tag_items); let mut found = None; let cls_items = match maybe_find_item(id, items) { Some(it) => it, None => fail (fmt!("class_dtor: class id not found \ when looking up dtor for %d", id)) }; - for ebml2::tagged_docs(cls_items, tag_item_dtor) |doc| { - let doc1 = ebml2::get_doc(doc, tag_def_id); - let did = ebml2::with_doc_data(doc1, |d| parse_def_id(d)); + for ebml::tagged_docs(cls_items, tag_item_dtor) |doc| { + let doc1 = ebml::get_doc(doc, tag_def_id); + let did = ebml::with_doc_data(doc1, |d| parse_def_id(d)); found = Some(translate_def_id(cdata, did)); }; found @@ -452,14 +453,14 @@ fn path_entry(path_string: ~str, def_like: def_like) -> path_entry { /// Iterates over all the paths in the given crate. fn each_path(intr: @ident_interner, cdata: cmd, f: fn(path_entry) -> bool) { - let root = ebml2::Doc(cdata.data); - let items = ebml2::get_doc(root, tag_items); - let items_data = ebml2::get_doc(items, tag_items_data); + let root = ebml::Doc(cdata.data); + let items = ebml::get_doc(root, tag_items); + let items_data = ebml::get_doc(items, tag_items_data); let mut broken = false; // First, go through all the explicit items. - for ebml2::tagged_docs(items_data, tag_items_data_item) |item_doc| { + for ebml::tagged_docs(items_data, tag_items_data_item) |item_doc| { if !broken { let path = ast_map::path_to_str_with_sep( item_path(intr, item_doc), ~"::", intr); @@ -482,16 +483,16 @@ fn each_path(intr: @ident_interner, cdata: cmd, f: fn(path_entry) -> bool) { for each_reexport(item_doc) |reexport_doc| { if !broken { let def_id_doc = - ebml2::get_doc(reexport_doc, + ebml::get_doc(reexport_doc, tag_items_data_item_reexport_def_id); let def_id = - ebml2::with_doc_data(def_id_doc, |d| parse_def_id(d)); + ebml::with_doc_data(def_id_doc, |d| parse_def_id(d)); let def_id = translate_def_id(cdata, def_id); let reexport_name_doc = - ebml2::get_doc(reexport_doc, + ebml::get_doc(reexport_doc, tag_items_data_item_reexport_name); - let reexport_name = ebml2::doc_as_str(reexport_name_doc); + let reexport_name = ebml::doc_as_str(reexport_name_doc); let reexport_path; if path == ~"" { @@ -540,7 +541,7 @@ type decode_inlined_item = fn( cdata: cstore::crate_metadata, tcx: ty::ctxt, path: ast_map::path, - par_doc: ebml2::Doc) -> Option; + par_doc: ebml::Doc) -> Option; fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt, id: ast::node_id, @@ -571,7 +572,7 @@ fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt, fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::variant_info] { let data = cdata.data; - let items = ebml2::get_doc(ebml2::Doc(data), tag_items); + let items = ebml::get_doc(ebml::Doc(data), tag_items); let item = find_item(id, items); let mut infos: ~[ty::variant_info] = ~[]; let variant_ids = enum_variant_ids(item, cdata); @@ -609,7 +610,7 @@ type method_info = { type _impl = {did: ast::def_id, ident: ast::ident, methods: ~[@method_info]}; -fn get_self_ty(item: ebml2::Doc) -> ast::self_ty_ { +fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ { fn get_mutability(ch: u8) -> ast::mutability { match ch as char { 'i' => { ast::m_imm } @@ -621,8 +622,8 @@ fn get_self_ty(item: ebml2::Doc) -> ast::self_ty_ { } } - let self_type_doc = ebml2::get_doc(item, tag_item_trait_method_self_ty); - let string = ebml2::doc_as_str(self_type_doc); + let self_type_doc = ebml::get_doc(item, tag_item_trait_method_self_ty); + let string = ebml::doc_as_str(self_type_doc); let self_ty_kind = string[0]; match self_ty_kind as char { @@ -638,11 +639,11 @@ fn get_self_ty(item: ebml2::Doc) -> ast::self_ty_ { } } -fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml2::Doc, +fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc, base_tps: uint) -> ~[@method_info] { let mut rslt = ~[]; - for ebml2::tagged_docs(item, tag_item_impl_method) |doc| { - let m_did = ebml2::with_doc_data(doc, |d| parse_def_id(d)); + for ebml::tagged_docs(item, tag_item_impl_method) |doc| { + let m_did = ebml::with_doc_data(doc, |d| parse_def_id(d)); let mth_item = lookup_item(m_did.node, cdata.data); let self_ty = get_self_ty(mth_item); rslt.push(@{did: translate_def_id(cdata, m_did), @@ -662,8 +663,8 @@ fn get_impls_for_mod(intr: @ident_interner, cdata: cmd, let data = cdata.data; let mod_item = lookup_item(m_id, data); let mut result = ~[]; - for ebml2::tagged_docs(mod_item, tag_mod_impl) |doc| { - let did = ebml2::with_doc_data(doc, |d| parse_def_id(d)); + for ebml::tagged_docs(mod_item, tag_mod_impl) |doc| { + let did = ebml::with_doc_data(doc, |d| parse_def_id(d)); let local_did = translate_def_id(cdata, did); debug!("(get impls for mod) getting did %? for '%?'", local_did, name); @@ -690,7 +691,7 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, let data = cdata.data; let item = lookup_item(id, data); let mut result = ~[]; - for ebml2::tagged_docs(item, tag_item_trait_method) |mth| { + for ebml::tagged_docs(item, tag_item_trait_method) |mth| { let bounds = item_ty_param_bounds(mth, tcx, cdata); let name = item_name(intr, mth); let ty = doc_type(mth, tcx, cdata); @@ -722,7 +723,7 @@ fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd, } let resulting_methods = @DVec(); - for ebml2::tagged_docs(item, tag_item_trait_method) |method| { + for ebml::tagged_docs(item, tag_item_trait_method) |method| { resulting_methods.push( (item_name(intr, method), get_self_ty(method))); } @@ -734,8 +735,8 @@ fn get_item_attrs(cdata: cmd, f: fn(~[@ast::meta_item])) { let item = lookup_item(node_id, cdata.data); - for ebml2::tagged_docs(item, tag_attributes) |attributes| { - for ebml2::tagged_docs(attributes, tag_attribute) |attribute| { + for ebml::tagged_docs(item, tag_attributes) |attributes| { + for ebml::tagged_docs(attributes, tag_attribute) |attribute| { f(get_meta_items(attribute)); } } @@ -747,7 +748,7 @@ fn get_class_members(intr: @ident_interner, cdata: cmd, id: ast::node_id, let data = cdata.data; let item = lookup_item(id, data); let mut result = ~[]; - for ebml2::tagged_docs(item, tag_item_field) |an_item| { + for ebml::tagged_docs(item, tag_item_field) |an_item| { let f = item_family(an_item); if p(f) { let name = item_name(intr, an_item); @@ -787,15 +788,15 @@ fn family_names_type(fam: Family) -> bool { match fam { Type | Mod | Trait => true, _ => false } } -fn read_path(d: ebml2::Doc) -> {path: ~str, pos: uint} { - let desc = ebml2::doc_data(d); +fn read_path(d: ebml::Doc) -> {path: ~str, pos: uint} { + let desc = ebml::doc_data(d); let pos = io::u64_from_be_bytes(desc, 0u, 4u) as uint; let pathbytes = vec::slice::(desc, 4u, vec::len::(desc)); let path = str::from_bytes(pathbytes); return {path: path, pos: pos}; } -fn describe_def(items: ebml2::Doc, id: ast::def_id) -> ~str { +fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str { if id.crate != ast::local_crate { return ~"external"; } let it = match maybe_find_item(id.node, items) { Some(it) => it, @@ -830,36 +831,36 @@ fn item_family_to_str(fam: Family) -> ~str { } } -fn get_meta_items(md: ebml2::Doc) -> ~[@ast::meta_item] { +fn get_meta_items(md: ebml::Doc) -> ~[@ast::meta_item] { let mut items: ~[@ast::meta_item] = ~[]; - for ebml2::tagged_docs(md, tag_meta_item_word) |meta_item_doc| { - let nd = ebml2::get_doc(meta_item_doc, tag_meta_item_name); - let n = str::from_bytes(ebml2::doc_data(nd)); + for ebml::tagged_docs(md, tag_meta_item_word) |meta_item_doc| { + let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name); + let n = str::from_bytes(ebml::doc_data(nd)); items.push(attr::mk_word_item(n)); }; - for ebml2::tagged_docs(md, tag_meta_item_name_value) |meta_item_doc| { - let nd = ebml2::get_doc(meta_item_doc, tag_meta_item_name); - let vd = ebml2::get_doc(meta_item_doc, tag_meta_item_value); - let n = str::from_bytes(ebml2::doc_data(nd)); - let v = str::from_bytes(ebml2::doc_data(vd)); + for ebml::tagged_docs(md, tag_meta_item_name_value) |meta_item_doc| { + let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name); + let vd = ebml::get_doc(meta_item_doc, tag_meta_item_value); + let n = str::from_bytes(ebml::doc_data(nd)); + let v = str::from_bytes(ebml::doc_data(vd)); // FIXME (#623): Should be able to decode meta_name_value variants, // but currently the encoder just drops them items.push(attr::mk_name_value_item_str(n, v)); }; - for ebml2::tagged_docs(md, tag_meta_item_list) |meta_item_doc| { - let nd = ebml2::get_doc(meta_item_doc, tag_meta_item_name); - let n = str::from_bytes(ebml2::doc_data(nd)); + for ebml::tagged_docs(md, tag_meta_item_list) |meta_item_doc| { + let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name); + let n = str::from_bytes(ebml::doc_data(nd)); let subitems = get_meta_items(meta_item_doc); items.push(attr::mk_list_item(n, subitems)); }; return items; } -fn get_attributes(md: ebml2::Doc) -> ~[ast::attribute] { +fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] { let mut attrs: ~[ast::attribute] = ~[]; - match ebml2::maybe_get_doc(md, tag_attributes) { + match ebml::maybe_get_doc(md, tag_attributes) { option::Some(attrs_d) => { - for ebml2::tagged_docs(attrs_d, tag_attribute) |attr_doc| { + for ebml::tagged_docs(attrs_d, tag_attribute) |attr_doc| { let meta_items = get_meta_items(attr_doc); // Currently it's only possible to have a single meta item on // an attribute @@ -877,13 +878,13 @@ fn get_attributes(md: ebml2::Doc) -> ~[ast::attribute] { } fn list_meta_items(intr: @ident_interner, - meta_items: ebml2::Doc, out: io::Writer) { + meta_items: ebml::Doc, out: io::Writer) { for get_meta_items(meta_items).each |mi| { out.write_str(fmt!("%s\n", pprust::meta_item_to_str(*mi, intr))); } } -fn list_crate_attributes(intr: @ident_interner, md: ebml2::Doc, hash: ~str, +fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: ~str, out: io::Writer) { out.write_str(fmt!("=Crate Attributes (%s)=\n", hash)); @@ -895,7 +896,7 @@ fn list_crate_attributes(intr: @ident_interner, md: ebml2::Doc, hash: ~str, } fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] { - return get_attributes(ebml2::Doc(data)); + return get_attributes(ebml::Doc(data)); } type crate_dep = {cnum: ast::crate_num, name: ast::ident, @@ -903,13 +904,13 @@ type crate_dep = {cnum: ast::crate_num, name: ast::ident, fn get_crate_deps(intr: @ident_interner, data: @~[u8]) -> ~[crate_dep] { let mut deps: ~[crate_dep] = ~[]; - let cratedoc = ebml2::Doc(data); - let depsdoc = ebml2::get_doc(cratedoc, tag_crate_deps); + let cratedoc = ebml::Doc(data); + let depsdoc = ebml::get_doc(cratedoc, tag_crate_deps); let mut crate_num = 1; - fn docstr(doc: ebml2::Doc, tag_: uint) -> ~str { - str::from_bytes(ebml2::doc_data(ebml2::get_doc(doc, tag_))) + fn docstr(doc: ebml::Doc, tag_: uint) -> ~str { + str::from_bytes(ebml::doc_data(ebml::get_doc(doc, tag_))) } - for ebml2::tagged_docs(depsdoc, tag_crate_dep) |depdoc| { + for ebml::tagged_docs(depsdoc, tag_crate_dep) |depdoc| { deps.push({cnum: crate_num, name: intr.intern(@docstr(depdoc, tag_crate_dep_name)), vers: docstr(depdoc, tag_crate_dep_vers), @@ -932,9 +933,9 @@ fn list_crate_deps(intr: @ident_interner, data: @~[u8], out: io::Writer) { } fn get_crate_hash(data: @~[u8]) -> ~str { - let cratedoc = ebml2::Doc(data); - let hashdoc = ebml2::get_doc(cratedoc, tag_crate_hash); - return str::from_bytes(ebml2::doc_data(hashdoc)); + let cratedoc = ebml::Doc(data); + let hashdoc = ebml::get_doc(cratedoc, tag_crate_hash); + return str::from_bytes(ebml::doc_data(hashdoc)); } fn get_crate_vers(data: @~[u8]) -> ~str { @@ -988,7 +989,7 @@ fn get_crate_module_paths(intr: @ident_interner, cdata: cmd) fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8], out: io::Writer) { let hash = get_crate_hash(bytes); - let md = ebml2::Doc(bytes); + let md = ebml::Doc(bytes); list_crate_attributes(intr, md, hash, out); list_crate_deps(intr, bytes, out); } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 95696a141566..f188d8ee5d8c 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -2,10 +2,10 @@ use util::ppaux::ty_to_str; -use std::{ebml2, map}; +use std::{ebml, map}; use std::map::HashMap; use io::WriterUtil; -use ebml2::Serializer; +use ebml::Serializer; use syntax::ast::*; use syntax::print::pprust; use syntax::{ast_util, visit}; @@ -40,7 +40,7 @@ export encode_def_id; type abbrev_map = map::HashMap; type encode_inlined_item = fn@(ecx: @encode_ctxt, - ebml_w: ebml2::Serializer, + ebml_w: ebml::Serializer, path: ast_map::path, ii: ast::inlined_item); @@ -86,15 +86,15 @@ fn reachable(ecx: @encode_ctxt, id: node_id) -> bool { ecx.reachable.contains_key(id) } -fn encode_name(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, name: ident) { +fn encode_name(ecx: @encode_ctxt, ebml_w: ebml::Serializer, name: ident) { ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name)); } -fn encode_def_id(ebml_w: ebml2::Serializer, id: def_id) { +fn encode_def_id(ebml_w: ebml::Serializer, id: def_id) { ebml_w.wr_tagged_str(tag_def_id, def_to_str(id)); } -fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::Serializer, it: @ast::item) { let opt_rp = ecx.tcx.region_paramd_items.find(it.id); for opt_rp.each |rp| { @@ -104,7 +104,7 @@ fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, } } -fn encode_mutability(ebml_w: ebml2::Serializer, mt: class_mutability) { +fn encode_mutability(ebml_w: ebml::Serializer, mt: class_mutability) { do ebml_w.wr_tag(tag_class_mut) { let val = match mt { class_immutable => 'a', @@ -116,7 +116,7 @@ fn encode_mutability(ebml_w: ebml2::Serializer, mt: class_mutability) { type entry = {val: T, pos: uint}; -fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, path: &[ident], +fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml::Serializer, path: &[ident], index: &mut ~[entry<~str>], name: ident) { let mut full_path = ~[]; full_path.push_all(path); @@ -127,7 +127,7 @@ fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, path: &[ident], pos: ebml_w.writer.tell()}); } -fn encode_trait_ref(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, +fn encode_trait_ref(ebml_w: ebml::Serializer, ecx: @encode_ctxt, t: @trait_ref) { ebml_w.start_tag(tag_impl_trait); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, t.ref_id)); @@ -136,7 +136,7 @@ fn encode_trait_ref(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, // Item info table encoding -fn encode_family(ebml_w: ebml2::Serializer, c: char) { +fn encode_family(ebml_w: ebml::Serializer, c: char) { ebml_w.start_tag(tag_items_data_item_family); ebml_w.writer.write(&[c as u8]); ebml_w.end_tag(); @@ -144,7 +144,7 @@ fn encode_family(ebml_w: ebml2::Serializer, c: char) { fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) } -fn encode_ty_type_param_bounds(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, +fn encode_ty_type_param_bounds(ebml_w: ebml::Serializer, ecx: @encode_ctxt, params: @~[ty::param_bounds]) { let ty_str_ctxt = @{diag: ecx.diag, ds: def_to_str, @@ -158,7 +158,7 @@ fn encode_ty_type_param_bounds(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, } } -fn encode_type_param_bounds(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, +fn encode_type_param_bounds(ebml_w: ebml::Serializer, ecx: @encode_ctxt, params: ~[ty_param]) { let ty_param_bounds = @params.map(|param| ecx.tcx.ty_param_bounds.get(param.id)); @@ -166,13 +166,13 @@ fn encode_type_param_bounds(ebml_w: ebml2::Serializer, ecx: @encode_ctxt, } -fn encode_variant_id(ebml_w: ebml2::Serializer, vid: def_id) { +fn encode_variant_id(ebml_w: ebml::Serializer, vid: def_id) { ebml_w.start_tag(tag_items_data_item_variant); ebml_w.writer.write(str::to_bytes(def_to_str(vid))); ebml_w.end_tag(); } -fn write_type(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, typ: ty::t) { +fn write_type(ecx: @encode_ctxt, ebml_w: ebml::Serializer, typ: ty::t) { let ty_str_ctxt = @{diag: ecx.diag, ds: def_to_str, @@ -182,7 +182,7 @@ fn write_type(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, typ: ty::t) { tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ); } -fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Serializer, vstore: ty::vstore) { let ty_str_ctxt = @{diag: ecx.diag, @@ -193,13 +193,13 @@ fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore); } -fn encode_type(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, typ: ty::t) { +fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::Serializer, typ: ty::t) { ebml_w.start_tag(tag_items_data_item_type); write_type(ecx, ebml_w, typ); ebml_w.end_tag(); } -fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, id: node_id) { +fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); let sym = match ecx.item_symbols.find(id) { Some(x) => x, @@ -212,27 +212,27 @@ fn encode_symbol(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, id: node_id) { ebml_w.end_tag(); } -fn encode_discriminant(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_discriminant(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); ebml_w.writer.write(str::to_bytes(ecx.discrim_symbols.get(id))); ebml_w.end_tag(); } -fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml::Serializer, disr_val: int) { ebml_w.start_tag(tag_disr_val); ebml_w.writer.write(str::to_bytes(int::to_str(disr_val,10u))); ebml_w.end_tag(); } -fn encode_parent_item(ebml_w: ebml2::Serializer, id: def_id) { +fn encode_parent_item(ebml_w: ebml::Serializer, id: def_id) { ebml_w.start_tag(tag_items_data_parent_item); ebml_w.writer.write(str::to_bytes(def_to_str(id))); ebml_w.end_tag(); } -fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id, variants: ~[variant], path: ast_map::path, index: @mut ~[entry], ty_params: ~[ty_param]) { @@ -269,9 +269,9 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, } } -fn encode_path(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_path(ecx: @encode_ctxt, ebml_w: ebml::Serializer, path: ast_map::path, name: ast_map::path_elt) { - fn encode_path_elt(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, + fn encode_path_elt(ecx: @encode_ctxt, ebml_w: ebml::Serializer, elt: ast_map::path_elt) { let (tag, name) = match elt { ast_map::path_mod(name) => (tag_path_elt_mod, name), @@ -290,7 +290,7 @@ fn encode_path(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, } } -fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, md: _mod, +fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::Serializer, md: _mod, id: node_id, path: ast_map::path, name: ident) { ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(id)); @@ -348,7 +348,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, md: _mod, ebml_w.end_tag(); } -fn encode_visibility(ebml_w: ebml2::Serializer, visibility: visibility) { +fn encode_visibility(ebml_w: ebml::Serializer, visibility: visibility) { encode_family(ebml_w, match visibility { public => 'g', private => 'j', @@ -356,7 +356,7 @@ fn encode_visibility(ebml_w: ebml2::Serializer, visibility: visibility) { }); } -fn encode_self_type(ebml_w: ebml2::Serializer, self_type: ast::self_ty_) { +fn encode_self_type(ebml_w: ebml::Serializer, self_type: ast::self_ty_) { ebml_w.start_tag(tag_item_trait_method_self_ty); // Encode the base self type. @@ -389,7 +389,7 @@ fn encode_self_type(ebml_w: ebml2::Serializer, self_type: ast::self_ty_) { } /* Returns an index of items in this class */ -fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id, path: ast_map::path, class_tps: ~[ty_param], fields: ~[@struct_field], @@ -445,7 +445,7 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, } // This is for encoding info for ctors and dtors -fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id, ident: ident, path: ast_map::path, item: Option, tps: ~[ty_param]) { ebml_w.start_tag(tag_items_data_item); @@ -470,7 +470,7 @@ fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, ebml_w.end_tag(); } -fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::Serializer, impl_path: ast_map::path, should_inline: bool, parent_id: node_id, m: @method, all_tps: ~[ty_param]) { @@ -520,7 +520,7 @@ fn should_inline(attrs: ~[attribute]) -> bool { } -fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, item: @item, index: @mut ~[entry], path: ast_map::path) { @@ -533,7 +533,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, }; if !must_write && !reachable(ecx, item.id) { return; } - fn add_to_index_(item: @item, ebml_w: ebml2::Serializer, + fn add_to_index_(item: @item, ebml_w: ebml::Serializer, index: @mut ~[entry]) { index.push({val: item.id, pos: ebml_w.writer.tell()}); } @@ -810,7 +810,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, } } -fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, nitem: @foreign_item, index: @mut ~[entry], path: ast_map::path, abi: foreign_abi) { @@ -843,7 +843,7 @@ fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, ebml_w.end_tag(); } -fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::Serializer, crate: @crate) -> ~[entry] { let index = @mut ~[]; ebml_w.start_tag(tag_items_data); @@ -898,7 +898,7 @@ fn create_index(index: ~[entry]) -> return buckets_frozen; } -fn encode_index(ebml_w: ebml2::Serializer, buckets: ~[@~[entry]], +fn encode_index(ebml_w: ebml::Serializer, buckets: ~[@~[entry]], write_fn: fn(io::Writer, T)) { let writer = ebml_w.writer; ebml_w.start_tag(tag_index); @@ -933,7 +933,7 @@ fn write_int(writer: io::Writer, &&n: int) { writer.write_be_u32(n as u32); } -fn encode_meta_item(ebml_w: ebml2::Serializer, mi: meta_item) { +fn encode_meta_item(ebml_w: ebml::Serializer, mi: meta_item) { match mi.node { meta_word(name) => { ebml_w.start_tag(tag_meta_item_word); @@ -970,7 +970,7 @@ fn encode_meta_item(ebml_w: ebml2::Serializer, mi: meta_item) { } } -fn encode_attributes(ebml_w: ebml2::Serializer, attrs: ~[attribute]) { +fn encode_attributes(ebml_w: ebml::Serializer, attrs: ~[attribute]) { ebml_w.start_tag(tag_attributes); for attrs.each |attr| { ebml_w.start_tag(tag_attribute); @@ -1031,7 +1031,7 @@ fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] { return attrs; } -fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::Serializer, cstore: cstore::cstore) { fn get_ordered_deps(ecx: @encode_ctxt, cstore: cstore::cstore) @@ -1077,7 +1077,7 @@ fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, ebml_w.end_tag(); } -fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, +fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml::Serializer, dep: decoder::crate_dep) { ebml_w.start_tag(tag_crate_dep); ebml_w.start_tag(tag_crate_dep_name); @@ -1092,7 +1092,7 @@ fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, ebml_w.end_tag(); } -fn encode_hash(ebml_w: ebml2::Serializer, hash: ~str) { +fn encode_hash(ebml_w: ebml::Serializer, hash: ~str) { ebml_w.start_tag(tag_crate_hash); ebml_w.writer.write(str::to_bytes(hash)); ebml_w.end_tag(); @@ -1130,7 +1130,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { type_abbrevs: ty::new_ty_hash() }); - let ebml_w = ebml2::Serializer(wr as io::Writer); + let ebml_w = ebml::Serializer(wr as io::Writer); encode_hash(ebml_w, ecx.link_meta.extras_hash); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 39ec58c079ed..103f1eecf87a 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -7,15 +7,14 @@ use syntax::visit; use syntax::ast_map; use syntax::ast_util; use syntax::codemap::span; -use std::ebml2; -use std::ebml2::Serializer; -use std::ebml2::get_doc; +use std::ebml; +use std::ebml::{Serializer, get_doc}; use std::map::HashMap; -use std::serialization2; -use std::serialization2::{Serializable, - SerializerHelpers, - DeserializerHelpers, - deserialize}; +use std::serialization; +use std::serialization::{Serializable, + SerializerHelpers, + DeserializerHelpers, + deserialize}; use middle::{ty, typeck}; use middle::typeck::{method_origin, method_map_entry, vtable_res, @@ -74,7 +73,7 @@ trait tr { // Top-level methods. fn encode_inlined_item(ecx: @e::encode_ctxt, - ebml_w: ebml2::Serializer, + ebml_w: ebml::Serializer, path: ast_map::path, ii: ast::inlined_item, maps: maps) { @@ -100,14 +99,14 @@ fn decode_inlined_item(cdata: cstore::crate_metadata, tcx: ty::ctxt, maps: maps, path: ast_map::path, - par_doc: ebml2::Doc) -> Option { + par_doc: ebml::Doc) -> Option { let dcx = @{cdata: cdata, tcx: tcx, maps: maps}; match par_doc.opt_child(c::tag_ast) { None => None, Some(ast_doc) => { debug!("> Decoding inlined fn: %s::?", ast_map::path_to_str(path, tcx.sess.parse_sess.interner)); - let ast_dsr = &ebml2::Deserializer(ast_doc); + let ast_dsr = &ebml::Deserializer(ast_doc); let from_id_range = deserialize(ast_dsr); let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range); let xcx = extended_decode_ctxt_(@{dcx: dcx, @@ -185,7 +184,7 @@ trait def_id_serializer_helpers { fn emit_def_id(did: ast::def_id); } -impl S: def_id_serializer_helpers { +impl S: def_id_serializer_helpers { fn emit_def_id(did: ast::def_id) { did.serialize(&self) } @@ -195,7 +194,7 @@ trait def_id_deserializer_helpers { fn read_def_id(xcx: extended_decode_ctxt) -> ast::def_id; } -impl D: def_id_deserializer_helpers { +impl D: def_id_deserializer_helpers { fn read_def_id(xcx: extended_decode_ctxt) -> ast::def_id { let did: ast::def_id = deserialize(&self); @@ -218,7 +217,7 @@ impl D: def_id_deserializer_helpers { // We also have to adjust the spans: for now we just insert a dummy span, // but eventually we should add entries to the local codemap as required. -fn encode_ast(ebml_w: ebml2::Serializer, item: ast::inlined_item) { +fn encode_ast(ebml_w: ebml::Serializer, item: ast::inlined_item) { do ebml_w.wr_tag(c::tag_tree as uint) { item.serialize(&ebml_w) } @@ -278,9 +277,9 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { } } -fn decode_ast(par_doc: ebml2::Doc) -> ast::inlined_item { +fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item { let chi_doc = par_doc[c::tag_tree as uint]; - let d = &ebml2::Deserializer(chi_doc); + let d = &ebml::Deserializer(chi_doc); deserialize(d) } @@ -332,12 +331,12 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) // ______________________________________________________________________ // Encoding and decoding of ast::def -fn encode_def(ebml_w: ebml2::Serializer, def: ast::def) { +fn encode_def(ebml_w: ebml::Serializer, def: ast::def) { def.serialize(&ebml_w) } -fn decode_def(xcx: extended_decode_ctxt, doc: ebml2::Doc) -> ast::def { - let dsr = &ebml2::Deserializer(doc); +fn decode_def(xcx: extended_decode_ctxt, doc: ebml::Doc) -> ast::def { + let dsr = &ebml::Deserializer(doc); let def: ast::def = deserialize(dsr); def.tr(xcx) } @@ -423,7 +422,7 @@ impl ty::bound_region: tr { // ______________________________________________________________________ // Encoding and decoding of freevar information -fn encode_freevar_entry(ebml_w: ebml2::Serializer, fv: @freevar_entry) { +fn encode_freevar_entry(ebml_w: ebml::Serializer, fv: @freevar_entry) { (*fv).serialize(&ebml_w) } @@ -431,7 +430,7 @@ trait ebml_deserializer_helper { fn read_freevar_entry(xcx: extended_decode_ctxt) -> freevar_entry; } -impl ebml2::Deserializer: ebml_deserializer_helper { +impl ebml::Deserializer: ebml_deserializer_helper { fn read_freevar_entry(xcx: extended_decode_ctxt) -> freevar_entry { let fv: freevar_entry = deserialize(&self); fv.tr(xcx) @@ -452,7 +451,7 @@ trait read_method_map_entry_helper { } fn serialize_method_map_entry(ecx: @e::encode_ctxt, - ebml_w: ebml2::Serializer, + ebml_w: ebml::Serializer, mme: method_map_entry) { do ebml_w.emit_rec { do ebml_w.emit_field(~"self_arg", 0u) { @@ -464,7 +463,7 @@ fn serialize_method_map_entry(ecx: @e::encode_ctxt, } } -impl ebml2::Deserializer: read_method_map_entry_helper { +impl ebml::Deserializer: read_method_map_entry_helper { fn read_method_map_entry(xcx: extended_decode_ctxt) -> method_map_entry { do self.read_rec { {self_arg: @@ -503,7 +502,7 @@ impl method_origin: tr { // Encoding and decoding vtable_res fn encode_vtable_res(ecx: @e::encode_ctxt, - ebml_w: ebml2::Serializer, + ebml_w: ebml::Serializer, dr: typeck::vtable_res) { // can't autogenerate this code because automatic serialization of // ty::t doesn't work, and there is no way (atm) to have @@ -515,7 +514,7 @@ fn encode_vtable_res(ecx: @e::encode_ctxt, } fn encode_vtable_origin(ecx: @e::encode_ctxt, - ebml_w: ebml2::Serializer, + ebml_w: ebml::Serializer, vtable_origin: typeck::vtable_origin) { do ebml_w.emit_enum(~"vtable_origin") { match vtable_origin { @@ -562,7 +561,7 @@ trait vtable_deserialization_helpers { fn read_vtable_origin(xcx: extended_decode_ctxt) -> typeck::vtable_origin; } -impl ebml2::Deserializer: vtable_deserialization_helpers { +impl ebml::Deserializer: vtable_deserialization_helpers { fn read_vtable_res(xcx: extended_decode_ctxt) -> typeck::vtable_res { @self.read_to_vec(|| self.read_vtable_origin(xcx) ) } @@ -639,7 +638,7 @@ trait ebml_writer_helpers { fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty); } -impl ebml2::Serializer: ebml_writer_helpers { +impl ebml::Serializer: ebml_writer_helpers { fn emit_ty(ecx: @e::encode_ctxt, ty: ty::t) { do self.emit_opaque { e::write_type(ecx, self, ty) @@ -692,7 +691,7 @@ trait write_tag_and_id { fn id(id: ast::node_id); } -impl ebml2::Serializer: write_tag_and_id { +impl ebml::Serializer: write_tag_and_id { fn tag(tag_id: c::astencode_tag, f: fn()) { do self.wr_tag(tag_id as uint) { f() } } @@ -704,7 +703,7 @@ impl ebml2::Serializer: write_tag_and_id { fn encode_side_tables_for_ii(ecx: @e::encode_ctxt, maps: maps, - ebml_w: ebml2::Serializer, + ebml_w: ebml::Serializer, ii: ast::inlined_item) { do ebml_w.wr_tag(c::tag_table as uint) { ast_util::visit_ids_for_inlined_item( @@ -720,7 +719,7 @@ fn encode_side_tables_for_ii(ecx: @e::encode_ctxt, fn encode_side_tables_for_id(ecx: @e::encode_ctxt, maps: maps, - ebml_w: ebml2::Serializer, + ebml_w: ebml::Serializer, id: ast::node_id) { let tcx = ecx.tcx; @@ -849,13 +848,13 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, trait doc_decoder_helpers { fn as_int() -> int; - fn opt_child(tag: c::astencode_tag) -> Option; + fn opt_child(tag: c::astencode_tag) -> Option; } -impl ebml2::Doc: doc_decoder_helpers { - fn as_int() -> int { ebml2::doc_as_u64(self) as int } - fn opt_child(tag: c::astencode_tag) -> Option { - ebml2::maybe_get_doc(self, tag as uint) +impl ebml::Doc: doc_decoder_helpers { + fn as_int() -> int { ebml::doc_as_u64(self) as int } + fn opt_child(tag: c::astencode_tag) -> Option { + ebml::maybe_get_doc(self, tag as uint) } } @@ -868,7 +867,7 @@ trait ebml_deserializer_decoder_helpers { -> ty::ty_param_bounds_and_ty; } -impl ebml2::Deserializer: ebml_deserializer_decoder_helpers { +impl ebml::Deserializer: ebml_deserializer_decoder_helpers { fn read_arg(xcx: extended_decode_ctxt) -> ty::arg { do self.read_opaque |doc| { @@ -923,10 +922,10 @@ impl ebml2::Deserializer: ebml_deserializer_decoder_helpers { } fn decode_side_tables(xcx: extended_decode_ctxt, - ast_doc: ebml2::Doc) { + ast_doc: ebml::Doc) { let dcx = xcx.dcx; let tbl_doc = ast_doc[c::tag_table as uint]; - for ebml2::docs(tbl_doc) |tag, entry_doc| { + for ebml::docs(tbl_doc) |tag, entry_doc| { let id0 = entry_doc[c::tag_table_id as uint].as_int(); let id = xcx.tr_id(id0); @@ -940,7 +939,7 @@ fn decode_side_tables(xcx: extended_decode_ctxt, dcx.tcx.legacy_boxed_traits.insert(id, ()); } else { let val_doc = entry_doc[c::tag_table_val as uint]; - let val_dsr = &ebml2::Deserializer(val_doc); + let val_dsr = &ebml::Deserializer(val_doc); if tag == (c::tag_table_def as uint) { let def = decode_def(xcx, val_doc); dcx.tcx.def_map.insert(id, def); @@ -993,16 +992,16 @@ fn decode_side_tables(xcx: extended_decode_ctxt, // Testing of astencode_gen #[cfg(test)] -fn encode_item_ast(ebml_w: ebml2::Serializer, item: @ast::item) { +fn encode_item_ast(ebml_w: ebml::Serializer, item: @ast::item) { do ebml_w.wr_tag(c::tag_tree as uint) { (*item).serialize(&ebml_w) } } #[cfg(test)] -fn decode_item_ast(par_doc: ebml2::Doc) -> @ast::item { +fn decode_item_ast(par_doc: ebml::Doc) -> @ast::item { let chi_doc = par_doc[c::tag_tree as uint]; - let d = &ebml2::Deserializer(chi_doc); + let d = &ebml::Deserializer(chi_doc); @deserialize(d) } @@ -1029,17 +1028,17 @@ fn mk_ctxt() -> fake_ext_ctxt { #[cfg(test)] fn roundtrip(in_item: @ast::item) { let bytes = do io::with_bytes_writer |wr| { - let ebml_w = ebml2::Serializer(wr); + let ebml_w = ebml::Serializer(wr); encode_item_ast(ebml_w, in_item); }; - let ebml_doc = ebml2::Doc(@bytes); + let ebml_doc = ebml::Doc(@bytes); let out_item = decode_item_ast(ebml_doc); let exp_str = do io::with_str_writer |w| { - in_item.serialize(&std::prettyprint2::Serializer(w)) + in_item.serialize(&std::prettyprint::Serializer(w)) }; let out_str = do io::with_str_writer |w| { - out_item.serialize(&std::prettyprint2::Serializer(w)) + out_item.serialize(&std::prettyprint::Serializer(w)) }; debug!("expected string: %s", exp_str); diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index d26b9566c97e..28400b5455d5 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -16,6 +16,8 @@ export has_freevars; // A vector of defs representing the free variables referred to in a function. // (The def_upvar will already have been stripped). +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type freevar_entry = { diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index bbc3a06fb675..85f03e1f0b33 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -211,6 +211,8 @@ type method = {ident: ast::ident, type mt = {ty: t, mutbl: ast::mutability}; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum vstore { @@ -271,6 +273,8 @@ enum ast_ty_to_ty_cache_entry { type opt_region_variance = Option; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum region_variance { rv_covariant, rv_invariant, rv_contravariant } @@ -289,6 +293,8 @@ impl region_variance : cmp::Eq { pure fn ne(other: ®ion_variance) -> bool { !self.eq(other) } } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type AutoAdjustment = { @@ -296,6 +302,8 @@ type AutoAdjustment = { autoref: Option }; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type AutoRef = { @@ -304,6 +312,8 @@ type AutoRef = { mutbl: ast::mutability }; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum AutoRefKind { @@ -509,6 +519,8 @@ impl param_ty : to_bytes::IterBytes { /// Representation of regions: +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum region { @@ -538,6 +550,8 @@ enum region { re_var(RegionVid) } +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum bound_region { @@ -669,6 +683,8 @@ enum param_bound { enum TyVid = uint; enum IntVid = uint; enum FnVid = uint; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum RegionVid = uint; diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index c2bd7f26bade..027a1d067423 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -75,6 +75,8 @@ export method_static, method_param, method_trait, method_self; export vtable_static, vtable_param, vtable_trait; export provided_methods_map; +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] enum method_origin { @@ -93,6 +95,8 @@ enum method_origin { // details for a method invoked with a receiver whose type is a type parameter // with a bounded trait. +#[auto_serialize] +#[auto_deserialize] #[auto_serialize2] #[auto_deserialize2] type method_param = { diff --git a/src/test/run-pass/auto_serialize2.rs b/src/test/run-pass/auto_serialize.rs similarity index 86% rename from src/test/run-pass/auto_serialize2.rs rename to src/test/run-pass/auto_serialize.rs index 4503ea6c7e01..6c85f59b74ed 100644 --- a/src/test/run-pass/auto_serialize2.rs +++ b/src/test/run-pass/auto_serialize.rs @@ -4,10 +4,10 @@ extern mod std; // the common code. use cmp::Eq; -use std::ebml2; +use std::ebml; use io::Writer; -use std::serialization2::{Serializable, Deserializable, deserialize}; -use std::prettyprint2; +use std::serialization::{Serializable, Deserializable, deserialize}; +use std::prettyprint; fn test_ser_and_deser( a1: &A, @@ -15,23 +15,23 @@ fn test_ser_and_deser( ) { // check the pretty printer: let s = do io::with_str_writer |w| { - a1.serialize(&prettyprint2::Serializer(w)) + a1.serialize(&prettyprint::Serializer(w)) }; debug!("s == %?", s); assert s == expected; // check the EBML serializer: let bytes = do io::with_bytes_writer |wr| { - let ebml_w = &ebml2::Serializer(wr); + let ebml_w = &ebml::Serializer(wr); a1.serialize(ebml_w) }; - let d = ebml2::Doc(@bytes); - let a2: A = deserialize(&ebml2::Deserializer(d)); + let d = ebml::Doc(@bytes); + let a2: A = deserialize(&ebml::Deserializer(d)); assert *a1 == a2; } -#[auto_serialize2] -#[auto_deserialize2] +#[auto_serialize] +#[auto_deserialize] enum Expr { Val(uint), Plus(@Expr, @Expr), @@ -105,8 +105,8 @@ impl CLike : cmp::Eq { pure fn ne(other: &CLike) -> bool { !self.eq(other) } } -#[auto_serialize2] -#[auto_deserialize2] +#[auto_serialize] +#[auto_deserialize] type Spanned = {lo: uint, hi: uint, node: T}; impl Spanned : cmp::Eq { @@ -116,27 +116,27 @@ impl Spanned : cmp::Eq { pure fn ne(other: &Spanned) -> bool { !self.eq(other) } } -#[auto_serialize2] -#[auto_deserialize2] +#[auto_serialize] +#[auto_deserialize] type SomeRec = {v: ~[uint]}; -#[auto_serialize2] -#[auto_deserialize2] +#[auto_serialize] +#[auto_deserialize] enum AnEnum = SomeRec; -#[auto_serialize2] -#[auto_deserialize2] +#[auto_serialize] +#[auto_deserialize] struct Point {x: uint, y: uint} -#[auto_serialize2] -#[auto_deserialize2] +#[auto_serialize] +#[auto_deserialize] enum Quark { Top(T), Bottom(T) } -#[auto_serialize2] -#[auto_deserialize2] +#[auto_serialize] +#[auto_deserialize] enum CLike { A, B, C } fn main() { From 91b7a9a529cad2db9503fa469b2e2ce7a86257e6 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sun, 7 Oct 2012 16:01:01 -0700 Subject: [PATCH 017/292] libcore: add first_ref and second_ref to tuples --- src/libcore/core.rs | 2 +- src/libcore/tuple.rs | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/libcore/core.rs b/src/libcore/core.rs index a14b67b40f13..603f19362ee4 100644 --- a/src/libcore/core.rs +++ b/src/libcore/core.rs @@ -11,7 +11,7 @@ pub use GenericPath = path::GenericPath; pub use WindowsPath = path::WindowsPath; pub use PosixPath = path::PosixPath; -pub use tuple::{TupleOps, ExtendedTupleOps}; +pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; pub use str::{StrSlice, UniqueStr}; pub use vec::{ConstVector, CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 246ce16c8131..899b16eb1320 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -6,13 +6,13 @@ use cmp::{Eq, Ord}; -pub trait TupleOps { +pub trait CopyableTuple { pure fn first() -> T; pure fn second() -> U; pure fn swap() -> (U, T); } -impl (T, U): TupleOps { +impl (T, U): CopyableTuple { /// Return the first element of self pure fn first() -> T { @@ -34,6 +34,24 @@ impl (T, U): TupleOps { } +pub trait ImmutableTuple { + pure fn first_ref(&self) -> &self/T; + pure fn second_ref(&self) -> &self/U; +} + +impl (T, U): ImmutableTuple { + pure fn first_ref(&self) -> &self/T { + match *self { + (ref t, _) => t, + } + } + pure fn second_ref(&self) -> &self/U { + match *self { + (_, ref u) => u, + } + } +} + pub trait ExtendedTupleOps { fn zip(&self) -> ~[(A, B)]; fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C]; @@ -145,6 +163,13 @@ impl (A, B, C) : Ord { pure fn gt(other: &(A, B, C)) -> bool { (*other).lt(&self) } } +#[test] +fn test_tuple_ref() { + let (~"foo", ~"bar"); + assert x.first_ref() == &~"foo"; + assert x.second_ref() == &~"bar"; +} + #[test] #[allow(non_implicitly_copyable_typarams)] fn test_tuple() { From 0bd6da8a8c93143325cb45e8a074ccf7121ca168 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sun, 7 Oct 2012 16:55:01 -0700 Subject: [PATCH 018/292] Remove old auto_serialize2 code (needs snapshot) --- src/libsyntax/ast.rs | 170 ----- src/libsyntax/ast_util.rs | 2 - src/libsyntax/ext/auto_serialize2.rs | 991 --------------------------- src/libsyntax/ext/base.rs | 61 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/parse/token.rs | 6 - src/libsyntax/syntax.rc | 3 - src/rustc/middle/freevars.rs | 2 - src/rustc/middle/ty.rs | 16 - src/rustc/middle/typeck.rs | 4 - 10 files changed, 2 insertions(+), 1255 deletions(-) delete mode 100644 src/libsyntax/ext/auto_serialize2.rs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f3e118461e66..a27336097d0c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -20,8 +20,6 @@ impl span: Deserializable { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type spanned = {node: T, span: span}; @@ -78,8 +76,6 @@ type fn_ident = Option; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type path = {span: span, global: bool, idents: ~[ident], @@ -92,8 +88,6 @@ type node_id = int; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type def_id = {crate: crate_num, node: node_id}; impl def_id : cmp::Eq { @@ -108,8 +102,6 @@ const crate_node_id: node_id = 0; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum ty_param_bound { bound_copy, bound_send, @@ -120,14 +112,10 @@ enum ty_param_bound { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum def { def_fn(def_id, purity), def_static_method(def_id, purity), @@ -308,8 +296,6 @@ type meta_item = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum meta_item_ { meta_word(~str), meta_list(~str, ~[@meta_item]), @@ -320,8 +306,6 @@ type blk = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type blk_ = {view_items: ~[@view_item], stmts: ~[@stmt], expr: Option<@expr>, @@ -330,20 +314,14 @@ type blk_ = {view_items: ~[@view_item], #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type pat = {id: node_id, node: pat_, span: span}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type field_pat = {ident: ident, pat: @pat}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum binding_mode { bind_by_value, bind_by_move, @@ -401,8 +379,6 @@ impl binding_mode : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -427,8 +403,6 @@ enum pat_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum mutability { m_mutbl, m_imm, m_const, } impl mutability : to_bytes::IterBytes { @@ -446,8 +420,6 @@ impl mutability : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum proto { proto_bare, // foreign fn proto_uniq, // fn~ @@ -464,8 +436,6 @@ impl proto : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -476,8 +446,6 @@ enum vstore { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum expr_vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) expr_vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -495,8 +463,6 @@ pure fn is_blockish(p: ast::proto) -> bool { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum binop { add, subtract, @@ -527,8 +493,6 @@ impl binop : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum unop { box(mutability), uniq(mutability), @@ -581,8 +545,6 @@ impl unop : cmp::Eq { // using ty::resolved_T(...). #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum inferable { expl(T), infer(node_id) @@ -623,8 +585,6 @@ impl inferable : cmp::Eq { // "resolved" mode: the real modes. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum rmode { by_ref, by_val, by_move, by_copy } impl rmode : to_bytes::IterBytes { @@ -648,8 +608,6 @@ type stmt = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum stmt_ { stmt_decl(@decl, node_id), @@ -662,8 +620,6 @@ enum stmt_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum init_op { init_assign, init_move, } impl init_op : cmp::Eq { @@ -688,16 +644,12 @@ impl init_op : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type initializer = {op: init_op, expr: @expr}; // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type local_ = {is_mutbl: bool, ty: @ty, pat: @pat, init: Option, id: node_id}; @@ -707,28 +659,20 @@ type decl = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum decl_ { decl_local(~[@local]), decl_item(@item), } #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type field_ = {mutbl: mutability, ident: ident, expr: @expr}; type field = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum blk_check_mode { default_blk, unsafe_blk, } impl blk_check_mode : cmp::Eq { @@ -745,28 +689,20 @@ impl blk_check_mode : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type expr = {id: node_id, callee_id: node_id, node: expr_, span: span}; // Extra node ID is only used for index, assign_op, unary, binary #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum log_level { error, debug, other } // 0 = error, 1 = debug, 2 = other #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum alt_mode { alt_check, alt_exhaustive, } #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum expr_ { expr_vstore(@expr, expr_vstore), expr_vec(~[@expr], mutability), @@ -824,8 +760,6 @@ enum expr_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type capture_item_ = { id: int, is_move: bool, @@ -855,8 +789,6 @@ type capture_clause = @~[capture_item]; // #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] #[doc="For macro invocations; parsing is delegated to the macro"] enum token_tree { tt_tok(span, token::token), @@ -922,8 +854,6 @@ type matcher = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum matcher_ { // match one token match_tok(token::token), @@ -940,16 +870,12 @@ type mac_arg = Option<@expr>; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type mac_body_ = {span: span}; type mac_body = Option; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum mac_ { mac_invoc(@path, mac_arg, mac_body), // old macro-invocation mac_invoc_tt(@path,~[token_tree]), // new macro-invocation @@ -964,8 +890,6 @@ type lit = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum lit_ { lit_str(@~str), lit_int(i64, int_ty), @@ -1008,30 +932,22 @@ impl ast::lit_: cmp::Eq { // type structure in middle/ty.rs as well. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type mt = {ty: @ty, mutbl: mutability}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type ty_field_ = {ident: ident, mt: mt}; type ty_field = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type ty_method = {ident: ident, attrs: ~[attribute], purity: purity, decl: fn_decl, tps: ~[ty_param], self_ty: self_ty, id: node_id, span: span}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] // A trait method is either required (meaning it doesn't have an // implementation, just a signature) or provided (meaning it has a default // implementation). @@ -1042,8 +958,6 @@ enum trait_method { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } impl int_ty : to_bytes::IterBytes { @@ -1074,8 +988,6 @@ impl int_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } impl uint_ty : to_bytes::IterBytes { @@ -1104,8 +1016,6 @@ impl uint_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum float_ty { ty_f, ty_f32, ty_f64, } impl float_ty : to_bytes::IterBytes { @@ -1125,15 +1035,11 @@ impl float_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type ty = {id: node_id, node: ty_, span: span}; // Not represented directly in the AST, referred to by name through a ty_path. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum prim_ty { ty_int(int_ty), ty_uint(uint_ty), @@ -1182,14 +1088,10 @@ impl prim_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type region = {id: node_id, node: region_}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum region_ { re_anon, re_static, @@ -1199,8 +1101,6 @@ enum region_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -1241,14 +1141,10 @@ impl ty : to_bytes::IterBytes { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type fn_decl = {inputs: ~[arg], output: @ty, @@ -1256,8 +1152,6 @@ type fn_decl = #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum purity { pure_fn, // declared with "pure fn" unsafe_fn, // declared with "unsafe fn" @@ -1280,8 +1174,6 @@ impl purity : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum ret_style { noreturn, // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) @@ -1308,8 +1200,6 @@ impl ret_style : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum self_ty_ { sty_static, // no self: static method sty_by_ref, // old by-reference self: `` @@ -1367,8 +1257,6 @@ type self_ty = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type method = {ident: ident, attrs: ~[attribute], tps: ~[ty_param], self_ty: self_ty, purity: purity, decl: fn_decl, body: blk, @@ -1377,14 +1265,10 @@ type method = {ident: ident, attrs: ~[attribute], #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type _mod = {view_items: ~[@view_item], items: ~[@item]}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum foreign_abi { foreign_abi_rust_intrinsic, foreign_abi_cdecl, @@ -1394,8 +1278,6 @@ enum foreign_abi { // Foreign mods can be named or anonymous #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum foreign_mod_sort { named, anonymous } impl foreign_mod_sort : cmp::Eq { @@ -1421,8 +1303,6 @@ impl foreign_abi : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type foreign_mod = {sort: foreign_mod_sort, view_items: ~[@view_item], @@ -1430,14 +1310,10 @@ type foreign_mod = #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type variant_arg = {ty: @ty, id: node_id}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum variant_kind { tuple_variant_kind(~[variant_arg]), struct_variant_kind(@struct_def), @@ -1446,20 +1322,14 @@ enum variant_kind { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type enum_def_ = { variants: ~[variant], common: Option<@struct_def> }; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum enum_def = enum_def_; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, id: node_id, disr_expr: Option<@expr>, vis: visibility}; @@ -1467,16 +1337,12 @@ type variant = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type path_list_ident_ = {name: ident, id: node_id}; type path_list_ident = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum namespace { module_ns, type_value_ns } impl namespace : cmp::Eq { @@ -1490,8 +1356,6 @@ type view_path = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum view_path_ { // quux = foo::bar::baz @@ -1510,15 +1374,11 @@ enum view_path_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type view_item = {node: view_item_, attrs: ~[attribute], vis: visibility, span: span}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum view_item_ { view_item_use(ident, ~[@meta_item], node_id), view_item_import(~[@view_path]), @@ -1533,8 +1393,6 @@ type attribute = spanned; // distinguished for pretty-printing. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum attr_style { attr_outer, attr_inner, } impl attr_style : cmp::Eq { @@ -1547,8 +1405,6 @@ impl attr_style : cmp::Eq { // doc-comments are promoted to attributes that have is_sugared_doc = true #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; /* @@ -1562,14 +1418,10 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; */ #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum visibility { public, private, inherited } impl visibility : cmp::Eq { @@ -1588,8 +1440,6 @@ impl visibility : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type struct_field_ = { kind: struct_field_kind, id: node_id, @@ -1600,8 +1450,6 @@ type struct_field = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum struct_field_kind { named_field(ident, class_mutability, visibility), unnamed_field // element of a tuple-like struct @@ -1609,8 +1457,6 @@ enum struct_field_kind { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type struct_def = { traits: ~[@trait_ref], /* traits this struct implements */ fields: ~[@struct_field], /* fields */ @@ -1628,16 +1474,12 @@ type struct_def = { */ #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type item = {ident: ident, attrs: ~[attribute], id: node_id, node: item_, vis: visibility, span: span}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum item_ { item_const(@ty, @expr), item_fn(fn_decl, purity, ~[ty_param], blk), @@ -1656,8 +1498,6 @@ enum item_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum class_mutability { class_mutable, class_immutable } impl class_mutability : to_bytes::IterBytes { @@ -1682,8 +1522,6 @@ type class_ctor = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type class_ctor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, @@ -1694,8 +1532,6 @@ type class_dtor = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type class_dtor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, @@ -1703,8 +1539,6 @@ type class_dtor_ = {id: node_id, #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type foreign_item = {ident: ident, attrs: ~[attribute], @@ -1715,8 +1549,6 @@ type foreign_item = #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum foreign_item_ { foreign_item_fn(fn_decl, purity, ~[ty_param]), foreign_item_const(@ty) @@ -1727,8 +1559,6 @@ enum foreign_item_ { // that we trans. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 897a51f710c6..ab24d7a53160 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -408,8 +408,6 @@ fn dtor_dec() -> fn_decl { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type id_range = {min: node_id, max: node_id}; fn empty(range: id_range) -> bool { diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs deleted file mode 100644 index b3102f8b4f72..000000000000 --- a/src/libsyntax/ext/auto_serialize2.rs +++ /dev/null @@ -1,991 +0,0 @@ -/* - -The compiler code necessary to implement the #[auto_serialize2] and -#[auto_deserialize2] extension. The idea here is that type-defining items may -be tagged with #[auto_serialize2] and #[auto_deserialize2], which will cause -us to generate a little companion module with the same name as the item. - -For example, a type like: - - #[auto_serialize2] - #[auto_deserialize2] - struct Node {id: uint} - -would generate two implementations like: - - impl Node: Serializable { - fn serialize(s: &S) { - do s.emit_struct("Node") { - s.emit_field("id", 0, || s.emit_uint(self)) - } - } - } - - impl node_id: Deserializable { - static fn deserialize(d: &D) -> Node { - do d.read_struct("Node") { - Node { - id: d.read_field(~"x", 0, || deserialize(d)) - } - } - } - } - -Other interesting scenarios are whe the item has type parameters or -references other non-built-in types. A type definition like: - - #[auto_serialize2] - #[auto_deserialize2] - type spanned = {node: T, span: span}; - -would yield functions like: - - impl spanned: Serializable { - fn serialize(s: &S) { - do s.emit_rec { - s.emit_field("node", 0, || self.node.serialize(s)); - s.emit_field("span", 1, || self.span.serialize(s)); - } - } - } - - impl spanned: Deserializable { - static fn deserialize(d: &D) -> spanned { - do d.read_rec { - { - node: d.read_field(~"node", 0, || deserialize(d)), - span: d.read_field(~"span", 1, || deserialize(d)), - } - } - } - } - -FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the -standard library. - -Misc notes: ------------ - -I use move mode arguments for ast nodes that will get inserted as is -into the tree. This is intended to prevent us from inserting the same -node twice. - -*/ - -use base::*; -use codemap::span; -use std::map; -use std::map::HashMap; - -export expand_auto_serialize; -export expand_auto_deserialize; - -// Transitional reexports so qquote can find the paths it is looking for -mod syntax { - pub use ext; - pub use parse; -} - -fn expand_auto_serialize( - cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - fn is_auto_serialize2(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) == ~"auto_serialize2" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize2(a)), - .. *item} - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_serialize2) { - match item.node { - ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { - let ser_impl = mk_rec_ser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_class(@{ fields, _}, tps) => { - let ser_impl = mk_struct_ser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_enum(enum_def, tps) => { - let ser_impl = mk_enum_ser_impl( - cx, - item.span, - item.ident, - enum_def, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_serialize2] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -fn expand_auto_deserialize( - cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - fn is_auto_deserialize2(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) == ~"auto_deserialize2" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize2(a)), - .. *item} - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_deserialize2) { - match item.node { - ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { - let deser_impl = mk_rec_deser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_class(@{ fields, _}, tps) => { - let deser_impl = mk_struct_deser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_enum(enum_def, tps) => { - let deser_impl = mk_enum_deser_impl( - cx, - item.span, - item.ident, - enum_def, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_deserialize2] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -fn mk_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - path: @ast::path, - tps: ~[ast::ty_param], - f: fn(@ast::ty) -> @ast::method -) -> @ast::item { - // All the type parameters need to bound to the trait. - let trait_tps = do tps.map |tp| { - let t_bound = ast::bound_trait(@{ - id: cx.next_id(), - node: ast::ty_path(path, cx.next_id()), - span: span, - }); - - { - ident: tp.ident, - id: cx.next_id(), - bounds: @vec::append(~[t_bound], *tp.bounds) - } - }; - - let opt_trait = Some(@{ - path: path, - ref_id: cx.next_id(), - impl_id: cx.next_id(), - }); - - let ty = cx.ty_path( - span, - ~[ident], - tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) - ); - - @{ - // This is a new-style impl declaration. - // XXX: clownshoes - ident: ast::token::special_idents::clownshoes_extensions, - attrs: ~[], - id: cx.next_id(), - node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), - vis: ast::public, - span: span, - } -} - -fn mk_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - tps: ~[ast::ty_param], - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialization2::Serializable trait. - let path = cx.path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Serializable"), - ] - ); - - mk_impl( - cx, - span, - ident, - path, - tps, - |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) - ) -} - -fn mk_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - tps: ~[ast::ty_param], - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialization2::Deserializable trait. - let path = cx.path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Deserializable"), - ] - ); - - mk_impl( - cx, - span, - ident, - path, - tps, - |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) - ) -} - -fn mk_ser_method( - cx: ext_ctxt, - span: span, - ser_body: ast::blk -) -> @ast::method { - let ser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Serializer"), - ], - ~[] - ); - - let ser_tps = ~[{ - ident: cx.ident_of(~"__S"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(ser_bound)], - }]; - - let ty_s = @{ - id: cx.next_id(), - node: ast::ty_rptr( - @{ - id: cx.next_id(), - node: ast::re_anon, - }, - { - ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), - mutbl: ast::m_imm - } - ), - span: span, - }; - - let ser_inputs = ~[{ - mode: ast::infer(cx.next_id()), - ty: ty_s, - ident: cx.ident_of(~"__s"), - id: cx.next_id(), - }]; - - let ser_output = @{ - id: cx.next_id(), - node: ast::ty_nil, - span: span, - }; - - let ser_decl = { - inputs: ser_inputs, - output: ser_output, - cf: ast::return_val, - }; - - @{ - ident: cx.ident_of(~"serialize"), - attrs: ~[], - tps: ser_tps, - self_ty: { node: ast::sty_region(ast::m_imm), span: span }, - purity: ast::impure_fn, - decl: ser_decl, - body: ser_body, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: ast::public, - } -} - -fn mk_deser_method( - cx: ext_ctxt, - span: span, - ty: @ast::ty, - deser_body: ast::blk -) -> @ast::method { - let deser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Deserializer"), - ], - ~[] - ); - - let deser_tps = ~[{ - ident: cx.ident_of(~"__D"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(deser_bound)], - }]; - - let ty_d = @{ - id: cx.next_id(), - node: ast::ty_rptr( - @{ - id: cx.next_id(), - node: ast::re_anon, - }, - { - ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), - mutbl: ast::m_imm - } - ), - span: span, - }; - - let deser_inputs = ~[{ - mode: ast::infer(cx.next_id()), - ty: ty_d, - ident: cx.ident_of(~"__d"), - id: cx.next_id(), - }]; - - let deser_decl = { - inputs: deser_inputs, - output: ty, - cf: ast::return_val, - }; - - @{ - ident: cx.ident_of(~"deserialize"), - attrs: ~[], - tps: deser_tps, - self_ty: { node: ast::sty_static, span: span }, - purity: ast::impure_fn, - decl: deser_decl, - body: deser_body, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: ast::public, - } -} - -fn mk_rec_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[ast::ty_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); - - // ast for `__s.emit_rec(|| $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_rec") - ), - ~[cx.lambda_stmts(span, fields)] - ); - - mk_ser_impl(cx, span, ident, tps, body) -} - -fn mk_rec_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[ast::ty_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); - - // ast for `read_rec(|| $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_rec") - ), - ~[ - cx.lambda_expr( - cx.expr( - span, - ast::expr_rec(fields, None) - ) - ) - ] - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -fn mk_struct_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[@ast::struct_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); - - // ast for `__s.emit_struct($(name), || $(fields))` - let ser_body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_struct") - ), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lambda_stmts(span, fields), - ] - ); - - mk_ser_impl(cx, span, ident, tps, ser_body) -} - -fn mk_struct_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[@ast::struct_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); - - // ast for `read_struct($(name), || $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_struct") - ), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lambda_expr( - cx.expr( - span, - ast::expr_struct( - cx.path(span, ~[ident]), - fields, - None - ) - ) - ), - ] - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -// Records and structs don't have the same fields types, but they share enough -// that if we extract the right subfields out we can share the serialization -// generator code. -type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; - -fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { - do fields.map |field| { - { - span: field.span, - ident: field.node.ident, - mutbl: field.node.mt.mutbl, - } - } -} - -fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { - do fields.map |field| { - let (ident, mutbl) = match field.node.kind { - ast::named_field(ident, mutbl, _) => (ident, mutbl), - _ => fail ~"[auto_serialize2] does not support \ - unnamed fields", - }; - - { - span: field.span, - ident: ident, - mutbl: match mutbl { - ast::class_mutable => ast::m_mutbl, - ast::class_immutable => ast::m_imm, - }, - } - } -} - -fn mk_ser_fields( - cx: ext_ctxt, - span: span, - fields: ~[field] -) -> ~[@ast::stmt] { - do fields.mapi |idx, field| { - // ast for `|| self.$(name).serialize(__s)` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"self"), - field.ident - ), - cx.ident_of(~"serialize") - ), - ~[cx.expr_var(span, ~"__s")] - ) - ); - - // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` - cx.stmt( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_field") - ), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ) - ) - } -} - -fn mk_deser_fields( - cx: ext_ctxt, - span: span, - fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] -) -> ~[ast::field] { - do fields.mapi |idx, field| { - // ast for `|| std::serialization2::deserialize(__d)` - let expr_lambda = cx.lambda( - cx.expr_blk( - cx.expr_call( - span, - cx.expr_path(span, ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"deserialize"), - ]), - ~[cx.expr_var(span, ~"__d")] - ) - ) - ); - - // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` - let expr: @ast::expr = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_field") - ), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ); - - { - node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, - span: span, - } - } -} - -fn mk_enum_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - tps: ~[ast::ty_param] -) -> @ast::item { - let body = mk_enum_ser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_ser_impl(cx, span, ident, tps, body) -} - -fn mk_enum_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - tps: ~[ast::ty_param] -) -> @ast::item { - let body = mk_enum_deser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -fn ser_variant( - cx: ext_ctxt, - span: span, - v_name: ast::ident, - v_idx: uint, - args: ~[ast::variant_arg] -) -> ast::arm { - // Name the variant arguments. - let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); - - // Bind the names to the variant argument type. - let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); - - let pat_node = if pats.is_empty() { - ast::pat_ident( - ast::bind_by_implicit_ref, - cx.path(span, ~[v_name]), - None - ) - } else { - ast::pat_enum( - cx.path(span, ~[v_name]), - Some(pats) - ) - }; - - let pat = @{ - id: cx.next_id(), - node: pat_node, - span: span, - }; - - let stmts = do args.mapi |a_idx, _arg| { - // ast for `__s.emit_enum_variant_arg` - let expr_emit = cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum_variant_arg") - ); - - // ast for `|| $(v).serialize(__s)` - let expr_serialize = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_path(span, ~[names[a_idx]]), - cx.ident_of(~"serialize") - ), - ~[cx.expr_var(span, ~"__s")] - ) - ); - - // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` - cx.stmt( - cx.expr_call( - span, - expr_emit, - ~[cx.lit_uint(span, a_idx), expr_serialize] - ) - ) - }; - - // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum_variant") - ), - ~[ - cx.lit_str(span, @cx.str_of(v_name)), - cx.lit_uint(span, v_idx), - cx.lit_uint(span, stmts.len()), - cx.lambda_stmts(span, stmts), - ] - ); - - { pats: ~[pat], guard: None, body: cx.expr_blk(body) } -} - -fn mk_enum_ser_body( - cx: ext_ctxt, - span: span, - name: ast::ident, - variants: ~[ast::variant] -) -> @ast::expr { - let arms = do variants.mapi |v_idx, variant| { - match variant.node.kind { - ast::tuple_variant_kind(args) => - ser_variant(cx, span, variant.node.name, v_idx, args), - ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented", - ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented", - } - }; - - // ast for `match *self { $(arms) }` - let match_expr = cx.expr( - span, - ast::expr_match( - cx.expr( - span, - ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) - ), - arms - ) - ); - - // ast for `__s.emit_enum($(name), || $(match_expr))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum") - ), - ~[ - cx.lit_str(span, @cx.str_of(name)), - cx.lambda_expr(match_expr), - ] - ) -} - -fn mk_enum_deser_variant_nary( - cx: ext_ctxt, - span: span, - name: ast::ident, - args: ~[ast::variant_arg] -) -> @ast::expr { - let args = do args.mapi |idx, _arg| { - // ast for `|| std::serialization2::deserialize(__d)` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_path(span, ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"deserialize"), - ]), - ~[cx.expr_var(span, ~"__d")] - ) - ); - - // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum_variant_arg") - ), - ~[cx.lit_uint(span, idx), expr_lambda] - ) - }; - - // ast for `$(name)($(args))` - cx.expr_call(span, cx.expr_path(span, ~[name]), args) -} - -fn mk_enum_deser_body( - cx: ext_ctxt, - span: span, - name: ast::ident, - variants: ~[ast::variant] -) -> @ast::expr { - let mut arms = do variants.mapi |v_idx, variant| { - let body = match variant.node.kind { - ast::tuple_variant_kind(args) => { - if args.is_empty() { - // for a nullary variant v, do "v" - cx.expr_path(span, ~[variant.node.name]) - } else { - // for an n-ary variant v, do "v(a_1, ..., a_n)" - mk_enum_deser_variant_nary( - cx, - span, - variant.node.name, - args - ) - } - }, - ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented", - ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented", - }; - - let pat = @{ - id: cx.next_id(), - node: ast::pat_lit(cx.lit_uint(span, v_idx)), - span: span, - }; - - { - pats: ~[pat], - guard: None, - body: cx.expr_blk(body), - } - }; - - let impossible_case = { - pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], - guard: None, - - // FIXME(#3198): proper error message - body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), - }; - - arms.push(impossible_case); - - // ast for `|i| { match i { $(arms) } }` - let expr_lambda = cx.expr( - span, - ast::expr_fn_block( - { - inputs: ~[{ - mode: ast::infer(cx.next_id()), - ty: @{ - id: cx.next_id(), - node: ast::ty_infer, - span: span - }, - ident: cx.ident_of(~"i"), - id: cx.next_id(), - }], - output: @{ - id: cx.next_id(), - node: ast::ty_infer, - span: span, - }, - cf: ast::return_val, - }, - cx.expr_blk( - cx.expr( - span, - ast::expr_match(cx.expr_var(span, ~"i"), arms) - ) - ), - @~[] - ) - ); - - // ast for `__d.read_enum_variant($(expr_lambda))` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum_variant") - ), - ~[expr_lambda] - ) - ); - - // ast for `__d.read_enum($(e_name), $(expr_lambda))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum") - ), - ~[ - cx.lit_str(span, @cx.str_of(name)), - expr_lambda - ] - ) -} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index ab56b6bb322e..c106042b9a3d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -54,7 +54,7 @@ enum syntax_extension { // macro_defining() is obsolete, remove when #old_macros go away. macro_defining(macro_definer), - // #[auto_serialize2] and such. will probably survive death of #old_macros + // #[auto_serialize] and such. will probably survive death of #old_macros item_decorator(item_decorator), // Token-tree expanders @@ -64,65 +64,6 @@ enum syntax_extension { // A temporary hard-coded map of methods for expanding syntax extension // AST nodes into full ASTs -#[cfg(stage0)] -fn syntax_expander_table() -> HashMap<~str, syntax_extension> { - fn builtin(f: syntax_expander_) -> syntax_extension - {normal({expander: f, span: None})} - fn builtin_expr_tt(f: syntax_expander_tt_) -> syntax_extension { - expr_tt({expander: f, span: None}) - } - fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension { - item_tt({expander: f, span: None}) - } - let syntax_expanders = HashMap(); - syntax_expanders.insert(~"macro", - macro_defining(ext::simplext::add_new_extension)); - syntax_expanders.insert(~"macro_rules", - builtin_item_tt( - ext::tt::macro_rules::add_new_extension)); - syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); - syntax_expanders.insert( - ~"auto_serialize2", - item_decorator(ext::auto_serialize2::expand_auto_serialize)); - syntax_expanders.insert( - ~"auto_deserialize2", - item_decorator(ext::auto_serialize2::expand_auto_deserialize)); - syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext)); - syntax_expanders.insert(~"concat_idents", - builtin(ext::concat_idents::expand_syntax_ext)); - syntax_expanders.insert(~"ident_to_str", - builtin(ext::ident_to_str::expand_syntax_ext)); - syntax_expanders.insert(~"log_syntax", - builtin_expr_tt( - ext::log_syntax::expand_syntax_ext)); - syntax_expanders.insert(~"ast", - builtin(ext::qquote::expand_ast)); - syntax_expanders.insert(~"line", - builtin(ext::source_util::expand_line)); - syntax_expanders.insert(~"col", - builtin(ext::source_util::expand_col)); - syntax_expanders.insert(~"file", - builtin(ext::source_util::expand_file)); - syntax_expanders.insert(~"stringify", - builtin(ext::source_util::expand_stringify)); - syntax_expanders.insert(~"include", - builtin(ext::source_util::expand_include)); - syntax_expanders.insert(~"include_str", - builtin(ext::source_util::expand_include_str)); - syntax_expanders.insert(~"include_bin", - builtin(ext::source_util::expand_include_bin)); - syntax_expanders.insert(~"module_path", - builtin(ext::source_util::expand_mod)); - syntax_expanders.insert(~"proto", - builtin_item_tt(ext::pipes::expand_proto)); - syntax_expanders.insert( - ~"trace_macros", - builtin_expr_tt(ext::trace_macros::expand_trace_macros)); - return syntax_expanders; -} - -#[cfg(stage1)] -#[cfg(stage2)] fn syntax_expander_table() -> HashMap<~str, syntax_extension> { fn builtin(f: syntax_expander_) -> syntax_extension {normal({expander: f, span: None})} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2d0b2f4c80ab..22e2cfcde6b5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -124,7 +124,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, } // This is a secondary mechanism for invoking syntax extensions on items: -// "decorator" attributes, such as #[auto_serialize2]. These are invoked by an +// "decorator" attributes, such as #[auto_serialize]. These are invoked by an // attribute prefixing an item, and are interpreted by feeding the item // through the named attribute _as a syntax extension_ and splicing in the // resulting item vec into place in favour of the decorator. Note that diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index b63260997f75..dce4dc3bbc7b 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -4,8 +4,6 @@ use std::map::HashMap; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum binop { PLUS, MINUS, @@ -21,8 +19,6 @@ enum binop { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum token { /* Expression-operator symbols. */ EQ, @@ -81,8 +77,6 @@ enum token { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] /// For interpolation during macro expansion. enum nonterminal { nt_item(@ast::item), diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 4c29fc5512a7..93ed5bd471bc 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -130,9 +130,6 @@ mod ext { mod log_syntax; #[legacy_exports] mod auto_serialize; - #[cfg(stage0)] - #[legacy_exports] - mod auto_serialize2; #[legacy_exports] mod source_util; diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index 28400b5455d5..1b42c9bb4b67 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -18,8 +18,6 @@ export has_freevars; // (The def_upvar will already have been stripped). #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type freevar_entry = { def: ast::def, //< The variable being accessed free. span: span //< First span where it is accessed (there can be multiple) diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 85f03e1f0b33..ca41be6f9d0a 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -213,8 +213,6 @@ type mt = {ty: t, mutbl: ast::mutability}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum vstore { vstore_fixed(uint), vstore_uniq, @@ -275,8 +273,6 @@ type opt_region_variance = Option; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum region_variance { rv_covariant, rv_invariant, rv_contravariant } impl region_variance : cmp::Eq { @@ -295,8 +291,6 @@ impl region_variance : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type AutoAdjustment = { autoderefs: uint, autoref: Option @@ -304,8 +298,6 @@ type AutoAdjustment = { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type AutoRef = { kind: AutoRefKind, region: region, @@ -314,8 +306,6 @@ type AutoRef = { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum AutoRefKind { /// Convert from @[]/~[] to &[] (or str) AutoSlice, @@ -521,8 +511,6 @@ impl param_ty : to_bytes::IterBytes { /// Representation of regions: #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions @@ -552,8 +540,6 @@ enum region { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum bound_region { /// The self region for classes, impls (&T in a type defn or &self/T) br_self, @@ -685,8 +671,6 @@ enum IntVid = uint; enum FnVid = uint; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum RegionVid = uint; enum InferTy { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 027a1d067423..7cb04bc0ea3c 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -77,8 +77,6 @@ export provided_methods_map; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum method_origin { // fully statically resolved method method_static(ast::def_id), @@ -97,8 +95,6 @@ enum method_origin { // with a bounded trait. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type method_param = { // the trait containing the method to be invoked trait_id: ast::def_id, From 0e7571b0607ee3920a2d29eee35fdf9e7e92442c Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sun, 7 Oct 2012 20:30:17 -0700 Subject: [PATCH 019/292] libcore Fix the tuple first_ref test --- src/libcore/tuple.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 899b16eb1320..ee9e0c84be6d 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -165,7 +165,7 @@ impl (A, B, C) : Ord { #[test] fn test_tuple_ref() { - let (~"foo", ~"bar"); + let x = (~"foo", ~"bar"); assert x.first_ref() == &~"foo"; assert x.second_ref() == &~"bar"; } From f5c3af1c1ab18632d2e8aa6c3a5fe369e670a471 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 7 Oct 2012 21:29:26 -0700 Subject: [PATCH 020/292] Clean up unfinished portions of task tutorial --- doc/tutorial-tasks.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md index 8b9d0c0c2a7d..1593184bce9f 100644 --- a/doc/tutorial-tasks.md +++ b/doc/tutorial-tasks.md @@ -36,6 +36,8 @@ explore some typical patterns in concurrent Rust code, and finally discuss some of the more exotic synchronization types in the standard library. +> ***Warning:*** This tutorial is incomplete + ## A note about the libraries While Rust's type system provides the building blocks needed for safe @@ -295,8 +297,6 @@ let result = ports.foldl(0, |accum, port| *accum + port.recv() ); # fn some_expensive_computation(_i: uint) -> int { 42 } ~~~ -# TODO - # Handling task failure Rust has a built-in mechanism for raising exceptions, written `fail` @@ -451,13 +451,6 @@ fail; # }; ~~~ - -# Unfinished notes - -## Actor patterns - -## Linearity, option dancing, owned closures - ## Creating a task with a bi-directional communication path A very common thing to do is to spawn a child task where the parent From ed3689d57c988e1dd477930d957c4308c37d1a64 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 5 Oct 2012 12:39:50 -0700 Subject: [PATCH 021/292] remove ctor from ast --- src/libsyntax/ast.rs | 9 +- src/libsyntax/ast_map.rs | 20 +- src/libsyntax/ast_util.rs | 13 +- src/libsyntax/fold.rs | 19 -- src/libsyntax/parse/parser.rs | 65 +----- src/libsyntax/print/pprust.rs | 12 -- src/libsyntax/visit.rs | 33 +-- src/rustc/metadata/decoder.rs | 6 +- src/rustc/metadata/encoder.rs | 22 +- src/rustc/middle/astencode.rs | 23 +- src/rustc/middle/borrowck/check_loans.rs | 60 ++---- src/rustc/middle/borrowck/gather_loans.rs | 10 +- src/rustc/middle/kind.rs | 6 +- src/rustc/middle/liveness.rs | 202 +++--------------- src/rustc/middle/region.rs | 20 +- src/rustc/middle/resolve.rs | 79 ++----- src/rustc/middle/trans/base.rs | 79 +------ src/rustc/middle/trans/common.rs | 5 - src/rustc/middle/trans/debuginfo.rs | 4 - src/rustc/middle/trans/inline.rs | 4 - src/rustc/middle/trans/monomorphize.rs | 13 +- src/rustc/middle/trans/reachable.rs | 11 - src/rustc/middle/trans/type_use.rs | 3 - src/rustc/middle/ty.rs | 5 +- src/rustc/middle/typeck/astconv.rs | 2 +- src/rustc/middle/typeck/check.rs | 16 +- src/rustc/middle/typeck/check/alt.rs | 2 +- src/rustc/middle/typeck/collect.rs | 24 --- src/test/compile-fail/issue-2590.rs | 2 +- .../compile-fail/regions-glb-free-free.rs | 2 +- 30 files changed, 120 insertions(+), 651 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1c279f81cc39..ced64daa8d61 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -135,7 +135,7 @@ enum def { @def, // closed over def node_id, // expr node that creates the closure node_id), // id for the block/body of the closure expr - def_class(def_id, bool /* has constructor */), + def_class(def_id), def_typaram_binder(node_id), /* class, impl or trait that has ty params */ def_region(node_id), def_label(node_id) @@ -235,9 +235,9 @@ impl def : cmp::Eq { _ => false } } - def_class(e0a, e1a) => { + def_class(e0a) => { match (*other) { - def_class(e0b, e1b) => e0a == e0b && e1a == e1b, + def_class(e0b) => e0a == e0b, _ => false } } @@ -1462,8 +1462,6 @@ type struct_def = { fields: ~[@struct_field], /* fields */ methods: ~[@method], /* methods */ /* (not including ctor or dtor) */ - /* ctor is optional, and will soon go away */ - ctor: Option, /* dtor is optional */ dtor: Option }; @@ -1563,7 +1561,6 @@ enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), ii_foreign(@foreign_item), - ii_ctor(class_ctor, ident, ~[ty_param], def_id /* parent id */), ii_dtor(class_dtor, ident, ~[ty_param], def_id /* parent id */) } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index d05c6eadaf6a..8555ceed2dbd 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -71,9 +71,6 @@ enum ast_node { // order they are introduced. node_arg(arg, uint), node_local(uint), - // Constructor for a class - // def_id is parent id - node_ctor(ident, ~[ty_param], @class_ctor, def_id, @path), // Destructor for a class node_dtor(~[ty_param], @class_dtor, def_id, @path), node_block(blk), @@ -132,7 +129,7 @@ fn map_decoded_item(diag: span_handler, // don't decode and instantiate the impl, but just the method, we have to // add it to the table now: match ii { - ii_item(*) | ii_ctor(*) | ii_dtor(*) => { /* fallthrough */ } + ii_item(*) | ii_dtor(*) => { /* fallthrough */ } ii_foreign(i) => { cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic, @path)); @@ -155,18 +152,6 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, cx.local_id += 1u; } match fk { - visit::fk_ctor(nm, attrs, tps, self_id, parent_id) => { - let ct = @{node: {id: id, - attrs: attrs, - self_id: self_id, - dec: /* FIXME (#2543) */ copy decl, - body: /* FIXME (#2543) */ copy body}, - span: sp}; - cx.map.insert(id, node_ctor(/* FIXME (#2543) */ copy nm, - /* FIXME (#2543) */ copy tps, - ct, parent_id, - @/* FIXME (#2543) */ copy cx.path)); - } visit::fk_dtor(tps, attrs, self_id, parent_id) => { let dt = @{node: {id: id, attrs: attrs, self_id: self_id, body: /* FIXME (#2543) */ copy body}, span: sp}; @@ -382,9 +367,6 @@ fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { Some(node_local(_)) => { // add more info here fmt!("local (id=%?)", id) } - Some(node_ctor(*)) => { // add more info here - fmt!("node_ctor (id=%?)", id) - } Some(node_dtor(*)) => { // add more info here fmt!("node_dtor (id=%?)", id) } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 47cbdb7ac6cb..9e44c42a7027 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -57,7 +57,7 @@ pure fn def_id_of_def(d: def) -> def_id { def_fn(id, _) | def_static_method(id, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | - def_use(id) | def_class(id, _) => { + def_use(id) | def_class(id) => { id } def_arg(id, _) | def_local(id, _) | def_self(id) | @@ -339,7 +339,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => /* FIXME (#2543) */ copy i.ident, ii_foreign(i) => /* FIXME (#2543) */ copy i.ident, ii_method(_, m) => /* FIXME (#2543) */ copy m.ident, - ii_ctor(_, nm, _, _) => /* FIXME (#2543) */ copy nm, ii_dtor(_, nm, _, _) => /* FIXME (#2543) */ copy nm } } @@ -349,7 +348,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => i.id, ii_foreign(i) => i.id, ii_method(_, m) => m.id, - ii_ctor(ctor, _, _, _) => ctor.node.id, ii_dtor(dtor, _, _, _) => dtor.node.id } } @@ -359,9 +357,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => v.visit_item(i, e, v), ii_foreign(i) => v.visit_foreign_item(i, e, v), ii_method(_, m) => visit::visit_method_helper(m, e, v), - ii_ctor(ctor, nm, tps, parent_id) => { - visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v); - } ii_dtor(dtor, _, tps, parent_id) => { visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v); } @@ -495,12 +490,6 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { vfn(id); match fk { - visit::fk_ctor(_, _, tps, self_id, parent_id) => { - for vec::each(tps) |tp| { vfn(tp.id); } - vfn(id); - vfn(self_id); - vfn(parent_id.node); - } visit::fk_dtor(tps, _, self_id, parent_id) => { for vec::each(tps) |tp| { vfn(tp.id); } vfn(id); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 088df01985ee..68d9cd80430d 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -271,23 +271,6 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold) -> @ast::struct_def { - let resulting_optional_constructor; - match struct_def.ctor { - None => { - resulting_optional_constructor = None; - } - Some(constructor) => { - resulting_optional_constructor = Some({ - node: { - body: fld.fold_block(constructor.node.body), - dec: fold_fn_decl(constructor.node.dec, fld), - id: fld.new_id(constructor.node.id), - .. constructor.node - }, - .. constructor - }); - } - } let dtor = do option::map(&struct_def.dtor) |dtor| { let dtor_body = fld.fold_block(dtor.node.body); let dtor_id = fld.new_id(dtor.node.id); @@ -298,7 +281,6 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold) traits: vec::map(struct_def.traits, |p| fold_trait_ref(*p, fld)), fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)), methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)), - ctor: resulting_optional_constructor, dtor: dtor }; } @@ -585,7 +567,6 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { |f| fld.fold_struct_field(*f)), methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)), - ctor: None, dtor: dtor }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 22c25186c918..f2e17c0a7e63 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -115,8 +115,7 @@ enum class_member { So that we can distinguish a class ctor or dtor from other class members */ -enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span), - dtor_decl(blk, ~[attribute], codemap::span), +enum class_contents { dtor_decl(blk, ~[attribute], codemap::span), members(~[@class_member]) } type arg_or_capture_item = Either; @@ -2683,30 +2682,13 @@ impl parser { let mut fields: ~[@struct_field]; let mut methods: ~[@method] = ~[]; - let mut the_ctor: Option<(fn_decl, ~[attribute], blk, codemap::span)> - = None; let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None; - let ctor_id = self.get_id(); if self.eat(token::LBRACE) { // It's a record-like struct. fields = ~[]; while self.token != token::RBRACE { match self.parse_class_item() { - ctor_decl(a_fn_decl, attrs, blk, s) => { - match the_ctor { - Some((_, _, _, s_first)) => { - self.span_note(s, #fmt("Duplicate constructor \ - declaration for class %s", - *self.interner.get(class_name))); - self.span_fatal(copy s_first, ~"First constructor \ - declared here"); - } - None => { - the_ctor = Some((a_fn_decl, attrs, blk, s)); - } - } - } dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { @@ -2764,36 +2746,14 @@ impl parser { self_id: self.get_id(), body: d_body}, span: d_s}}; - match the_ctor { - Some((ct_d, ct_attrs, ct_b, ct_s)) => { - (class_name, - item_class(@{ - traits: traits, - fields: move fields, - methods: move methods, - ctor: Some({ - node: {id: ctor_id, - attrs: ct_attrs, - self_id: self.get_id(), - dec: ct_d, - body: ct_b}, - span: ct_s}), - dtor: actual_dtor - }, ty_params), - None) - } - None => { - (class_name, - item_class(@{ - traits: traits, - fields: move fields, - methods: move methods, - ctor: None, - dtor: actual_dtor - }, ty_params), - None) - } - } + (class_name, + item_class(@{ + traits: traits, + fields: move fields, + methods: move methods, + dtor: actual_dtor + }, ty_params), + None) } fn token_is_pound_or_doc_comment(++tok: token::token) -> bool { @@ -3097,12 +3057,6 @@ impl parser { let mut methods: ~[@method] = ~[]; while self.token != token::RBRACE { match self.parse_class_item() { - ctor_decl(*) => { - self.span_fatal(copy self.span, - ~"deprecated explicit \ - constructors are not allowed \ - here"); - } dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { @@ -3143,7 +3097,6 @@ impl parser { traits: ~[], fields: move fields, methods: move methods, - ctor: None, dtor: actual_dtor }; } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index bff356e5cb72..b98014f421bb 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -653,18 +653,6 @@ fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param], } bopen(s); hardbreak_if_not_bol(s); - do struct_def.ctor.iter |ctor| { - maybe_print_comment(s, ctor.span.lo); - print_outer_attributes(s, ctor.node.attrs); - // Doesn't call head because there shouldn't be a space after new. - cbox(s, indent_unit); - ibox(s, 4); - word(s.s, ~"new("); - print_fn_args(s, ctor.node.dec, ~[], None); - word(s.s, ~")"); - space(s.s); - print_block(s, ctor.node.body); - } do struct_def.dtor.iter |dtor| { hardbreak_if_not_bol(s); maybe_print_comment(s, dtor.span.lo); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index e6fd65eb458a..50fbd21f7b8d 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -17,8 +17,6 @@ enum fn_kind { fk_method(ident, ~[ty_param], @method), fk_anon(proto, capture_clause), //< an anonymous function like fn@(...) fk_fn_block(capture_clause), //< a block {||...} - fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */, - def_id /* parent class id */), // class constructor fk_dtor(~[ty_param], ~[attribute], node_id /* self id */, def_id /* parent class id */) // class destructor @@ -26,8 +24,9 @@ enum fn_kind { fn name_of_fn(fk: fn_kind) -> ident { match fk { - fk_item_fn(name, _, _) | fk_method(name, _, _) - | fk_ctor(name, _, _, _, _) => /* FIXME (#2543) */ copy name, + fk_item_fn(name, _, _) | fk_method(name, _, _) => { + /* FIXME (#2543) */ copy name + } fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon, fk_dtor(*) => parse::token::special_idents::dtor } @@ -35,11 +34,11 @@ fn name_of_fn(fk: fn_kind) -> ident { fn tps_of_fn(fk: fn_kind) -> ~[ty_param] { match fk { - fk_item_fn(_, tps, _) | fk_method(_, tps, _) - | fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) => { - /* FIXME (#2543) */ copy tps - } - fk_anon(*) | fk_fn_block(*) => ~[] + fk_item_fn(_, tps, _) | fk_method(_, tps, _) | + fk_dtor(tps, _, _, _) => { + /* FIXME (#2543) */ copy tps + } + fk_anon(*) | fk_fn_block(*) => ~[] } } @@ -291,17 +290,6 @@ fn visit_method_helper(m: @method, e: E, v: vt) { m.decl, m.body, m.span, m.id, e, v); } -// Similar logic to the comment on visit_method_helper - Tim -fn visit_class_ctor_helper(ctor: class_ctor, nm: ident, tps: ~[ty_param], - parent_id: def_id, e: E, v: vt) { - v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm, - ctor.node.attrs, - /* FIXME (#2543) */ copy tps, - ctor.node.self_id, parent_id), - ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v) - -} - fn visit_class_dtor_helper(dtor: class_dtor, tps: ~[ty_param], parent_id: def_id, e: E, v: vt) { v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs, @@ -330,7 +318,7 @@ fn visit_trait_method(m: trait_method, e: E, v: vt) { } } -fn visit_struct_def(sd: @struct_def, nm: ast::ident, tps: ~[ty_param], +fn visit_struct_def(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param], id: node_id, e: E, v: vt) { for sd.fields.each |f| { v.visit_struct_field(*f, e, v); @@ -341,9 +329,6 @@ fn visit_struct_def(sd: @struct_def, nm: ast::ident, tps: ~[ty_param], for sd.traits.each |p| { visit_path(p.path, e, v); } - do option::iter(&sd.ctor) |ctor| { - visit_class_ctor_helper(*ctor, nm, tps, ast_util::local_def(id), e, v); - }; do option::iter(&sd.dtor) |dtor| { visit_class_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v) }; diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 197e567ab2f8..70a47522f379 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -123,7 +123,6 @@ enum Family { Variant, // v Impl, // i Trait, // I - Class, // C Struct, // S PublicField, // g PrivateField, // j @@ -156,7 +155,6 @@ fn item_family(item: ebml2::Doc) -> Family { 'v' => Variant, 'i' => Impl, 'I' => Trait, - 'C' => Class, 'S' => Struct, 'g' => PublicField, 'j' => PrivateField, @@ -300,8 +298,7 @@ fn item_to_def_like(item: ebml2::Doc, did: ast::def_id, cnum: ast::crate_num) let fam = item_family(item); match fam { Const => dl_def(ast::def_const(did)), - Class => dl_def(ast::def_class(did, true)), - Struct => dl_def(ast::def_class(did, false)), + Struct => dl_def(ast::def_class(did)), UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), Fn => dl_def(ast::def_fn(did, ast::impure_fn)), PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), @@ -822,7 +819,6 @@ fn item_family_to_str(fam: Family) -> ~str { Variant => ~"variant", Impl => ~"impl", Trait => ~"trait", - Class => ~"class", Struct => ~"struct", PublicField => ~"public field", PrivateField => ~"private field", diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 95696a141566..ce3f50e71842 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -635,12 +635,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, /* Now, make an item for the class itself */ ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); - - match struct_def.ctor { - None => encode_family(ebml_w, 'S'), - Some(_) => encode_family(ebml_w, 'C') - } - + encode_family(ebml_w, 'S'); encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); @@ -699,21 +694,6 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, let bkts = create_index(idx); encode_index(ebml_w, bkts, write_int); ebml_w.end_tag(); - - /* Encode the constructor */ - for struct_def.ctor.each |ctor| { - debug!("encoding info for ctor %s %d", - ecx.tcx.sess.str_of(item.ident), ctor.node.id); - index.push({ - val: ctor.node.id, - pos: ebml_w.writer.tell() - }); - encode_info_for_ctor(ecx, ebml_w, ctor.node.id, item.ident, - path, if tps.len() > 0u { - Some(ii_ctor(*ctor, item.ident, tps, - local_def(item.id))) } - else { None }, tps); - } } item_impl(tps, opt_trait, _, methods) => { add_to_index(); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 39ec58c079ed..95c3d08f60e5 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -262,13 +262,6 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } - ast::ii_ctor(ctor, nm, tps, parent_id) => { - let ctor_body = fld.fold_block(ctor.node.body); - let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); - ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl, - .. ctor.node}, - .. ctor}, nm, tps, parent_id) - } ast::ii_dtor(dtor, nm, tps, parent_id) => { let dtor_body = fld.fold_block(dtor.node.body); ast::ii_dtor({node: {body: dtor_body, @@ -302,18 +295,6 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } - ast::ii_ctor(ctor, nm, tps, parent_id) => { - let ctor_body = fld.fold_block(ctor.node.body); - let ctor_attrs = fld.fold_attributes(ctor.node.attrs); - let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); - let new_params = fold::fold_ty_params(tps, fld); - let ctor_id = fld.new_id(ctor.node.id); - let new_parent = xcx.tr_def_id(parent_id); - ast::ii_ctor({node: {body: ctor_body, attrs: ctor_attrs, - dec: ctor_decl, id: ctor_id, - .. ctor.node}, - .. ctor}, nm, new_params, new_parent) - } ast::ii_dtor(dtor, nm, tps, parent_id) => { let dtor_body = fld.fold_block(dtor.node.body); let dtor_attrs = fld.fold_attributes(dtor.node.attrs); @@ -369,8 +350,8 @@ impl ast::def: tr { xcx.tr_id(nid2), xcx.tr_id(nid3)) } - ast::def_class(did, has_constructor) => { - ast::def_class(did.tr(xcx), has_constructor) + ast::def_class(did) => { + ast::def_class(did.tr(xcx)) } ast::def_region(nid) => ast::def_region(xcx.tr_id(nid)), ast::def_typaram_binder(nid) => { diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index cc8d89a8ace7..6a9195b45096 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -17,10 +17,6 @@ enum check_loan_ctxt = @{ reported: HashMap, - // Keep track of whether we're inside a ctor, so as to - // allow mutating immutable fields in the same class if - // we are in a ctor, we track the self id - mut in_ctor: bool, mut declared_purity: ast::purity, mut fn_args: @~[ast::node_id] }; @@ -62,7 +58,6 @@ fn check_loans(bccx: borrowck_ctxt, let clcx = check_loan_ctxt(@{bccx: bccx, req_maps: req_maps, reported: HashMap(), - mut in_ctor: false, mut declared_purity: ast::impure_fn, mut fn_args: @~[]}); let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr, @@ -320,10 +315,7 @@ impl check_loan_ctxt { debug!("check_assignment(cmt=%s)", self.bccx.cmt_to_repr(cmt)); - if self.in_ctor && self.is_self_field(cmt) - && at.checked_by_liveness() { - // assigning to self.foo in a ctor is always allowed. - } else if self.is_local_variable(cmt) && at.checked_by_liveness() { + if self.is_local_variable(cmt) && at.checked_by_liveness() { // liveness guarantees that immutable local variables // are only assigned once } else { @@ -542,42 +534,28 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visitor: visit::vt) { debug!("purity on entry=%?", copy self.declared_purity); - do save_and_restore(&mut(self.in_ctor)) { - do save_and_restore(&mut(self.declared_purity)) { - do save_and_restore(&mut(self.fn_args)) { - let is_stack_closure = self.is_stack_closure(id); - let fty = ty::node_id_to_type(self.tcx(), id); - self.declared_purity = ty::determine_inherited_purity( - copy self.declared_purity, - ty::ty_fn_purity(fty), - ty::ty_fn_proto(fty)); + do save_and_restore(&mut(self.declared_purity)) { + do save_and_restore(&mut(self.fn_args)) { + let is_stack_closure = self.is_stack_closure(id); + let fty = ty::node_id_to_type(self.tcx(), id); + self.declared_purity = ty::determine_inherited_purity( + copy self.declared_purity, + ty::ty_fn_purity(fty), + ty::ty_fn_proto(fty)); - // In principle, we could consider fk_anon(*) or - // fk_fn_block(*) to be in a ctor, I suppose, but the - // purpose of the in_ctor flag is to allow modifications - // of otherwise immutable fields and typestate wouldn't be - // able to "see" into those functions anyway, so it - // wouldn't be very helpful. - match fk { - visit::fk_ctor(*) => { - self.in_ctor = true; - self.fn_args = @decl.inputs.map(|i| i.id ); - } - visit::fk_anon(*) | - visit::fk_fn_block(*) if is_stack_closure => { - self.in_ctor = false; + match fk { + visit::fk_anon(*) | + visit::fk_fn_block(*) if is_stack_closure => { // inherits the fn_args from enclosing ctxt - } - visit::fk_anon(*) | visit::fk_fn_block(*) | - visit::fk_method(*) | visit::fk_item_fn(*) | - visit::fk_dtor(*) => { - self.in_ctor = false; - self.fn_args = @decl.inputs.map(|i| i.id ); - } } - - visit::visit_fn(fk, decl, body, sp, id, self, visitor); + visit::fk_anon(*) | visit::fk_fn_block(*) | + visit::fk_method(*) | visit::fk_item_fn(*) | + visit::fk_dtor(*) => { + self.fn_args = @decl.inputs.map(|i| i.id ); + } } + + visit::visit_fn(fk, decl, body, sp, id, self, visitor); } } debug!("purity on exit=%?", copy self.declared_purity); diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index 5dfde8c9af64..2a23ec86c514 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -71,11 +71,11 @@ fn req_loans_in_fn(fk: visit::fn_kind, self.root_ub = body.node.id; match fk { - visit::fk_anon(*) | visit::fk_fn_block(*) => {} - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => { - self.item_ub = body.node.id; - } + visit::fk_anon(*) | visit::fk_fn_block(*) => {} + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => { + self.item_ub = body.node.id; + } } visit::visit_fn(fk, decl, body, sp, id, self, v); diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index e2b85441a8fd..7b473cedb4c5 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -181,9 +181,9 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, // variables. This list is used below to avoid checking and reporting // on a given variable twice. let cap_clause = match fk { - visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc, - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => @~[] + visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc, + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => @~[] }; let captured_vars = do (*cap_clause).map |cap_item| { let cap_def = cx.tcx.def_map.get(cap_item.id); diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 12d63cdacbf6..86f786e7706f 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -35,12 +35,6 @@ * Any use of the variable where the variable is dead afterwards is a * last use. * - * # Extension to handle constructors - * - * Each field is assigned an index just as with local variables. A use of - * `self` is considered a use of all fields. A use of `self.f` is just a use - * of `f`. - * * # Implementation details * * The actual implementation contains two (nested) walks over the AST. @@ -96,8 +90,6 @@ * - `no_ret_var`: a synthetic variable that is only 'read' from, the * fallthrough node. This allows us to detect functions where we fail * to return explicitly. - * - * - `self_var`: a variable representing 'self' */ use dvec::DVec; @@ -230,7 +222,7 @@ impl LiveNode { fn invalid_node() -> LiveNode { LiveNode(uint::max_value) } -enum RelevantDef { RelevantVar(node_id), RelevantSelf } +enum RelevantDef { RelevantVar(node_id) } type CaptureInfo = {ln: LiveNode, is_move: bool, rv: RelevantDef}; @@ -250,15 +242,12 @@ struct LocalInfo { enum VarKind { Arg(node_id, ident, rmode), Local(LocalInfo), - Field(ident), Self, ImplicitRet } fn relevant_def(def: def) -> Option { match def { - def_self(_) => Some(RelevantSelf), - def_binding(nid, _) | def_arg(nid, _) | def_local(nid, _) => Some(RelevantVar(nid)), @@ -276,7 +265,6 @@ struct IrMaps { mut num_vars: uint, live_node_map: HashMap, variable_map: HashMap, - field_map: HashMap, capture_map: HashMap, mut var_kinds: ~[VarKind], mut lnks: ~[LiveNodeKind], @@ -293,7 +281,6 @@ fn IrMaps(tcx: ty::ctxt, method_map: typeck::method_map, live_node_map: HashMap(), variable_map: HashMap(), capture_map: HashMap(), - field_map: HashMap(), var_kinds: ~[], lnks: ~[] } @@ -323,15 +310,12 @@ impl IrMaps { self.num_vars += 1u; match vk { - Local(LocalInfo {id:node_id, _}) | - Arg(node_id, _, _) => { - self.variable_map.insert(node_id, v); - } - Field(name) => { - self.field_map.insert(name, v); - } - Self | ImplicitRet => { - } + Local(LocalInfo {id:node_id, _}) | + Arg(node_id, _, _) => { + self.variable_map.insert(node_id, v); + } + Self | ImplicitRet => { + } } debug!("%s is %?", v.to_str(), vk); @@ -351,11 +335,10 @@ impl IrMaps { fn variable_name(var: Variable) -> ~str { match copy self.var_kinds[*var] { - Local(LocalInfo {ident: nm, _}) | - Arg(_, nm, _) => self.tcx.sess.str_of(nm), - Field(nm) => ~"self." + self.tcx.sess.str_of(nm), - Self => ~"self", - ImplicitRet => ~"" + Local(LocalInfo {ident: nm, _}) | + Arg(_, nm, _) => self.tcx.sess.str_of(nm), + Self => ~"self", + ImplicitRet => ~"" } } @@ -399,7 +382,7 @@ impl IrMaps { (*v).push(id); } Arg(_, _, by_ref) | - Arg(_, _, by_val) | Self | Field(_) | ImplicitRet | + Arg(_, _, by_val) | Self | ImplicitRet | Local(LocalInfo {kind: FromMatch(bind_by_implicit_ref), _}) => { debug!("--but it is not owned"); } @@ -428,13 +411,6 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, // and so forth: visit::visit_fn(fk, decl, body, sp, id, fn_maps, v); - match fk { - visit::fk_ctor(_, _, _, _, class_did) => { - add_class_fields(fn_maps, class_did); - } - _ => {} - } - // Special nodes and variables: // - exit_ln represents the end of the fn, either by return or fail // - implicit_ret_var is a pseudo-variable that represents @@ -442,8 +418,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, let specials = { exit_ln: (*fn_maps).add_live_node(ExitNode), fallthrough_ln: (*fn_maps).add_live_node(ExitNode), - no_ret_var: (*fn_maps).add_variable(ImplicitRet), - self_var: (*fn_maps).add_variable(Self) + no_ret_var: (*fn_maps).add_variable(ImplicitRet) }; // compute liveness @@ -460,18 +435,9 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, }); check_vt.visit_block(body, lsets, check_vt); lsets.check_ret(id, sp, fk, entry_ln); - lsets.check_fields(sp, entry_ln); lsets.warn_about_unused_args(sp, decl, entry_ln); } -fn add_class_fields(self: @IrMaps, did: def_id) { - for ty::lookup_class_fields(self.tcx, did).each |field_ty| { - assert field_ty.id.crate == local_crate; - let var = self.add_variable(Field(field_ty.ident)); - self.field_map.insert(field_ty.ident, var); - } -} - fn visit_local(local: @local, &&self: @IrMaps, vt: vt<@IrMaps>) { let def_map = self.tcx.def_map; do pat_util::pat_bindings(def_map, local.node.pat) |_bm, p_id, sp, path| { @@ -595,8 +561,7 @@ fn invalid_users() -> users { type Specials = { exit_ln: LiveNode, fallthrough_ln: LiveNode, - no_ret_var: Variable, - self_var: Variable + no_ret_var: Variable }; const ACC_READ: uint = 1u; @@ -649,7 +614,6 @@ impl Liveness { fn variable_from_rdef(rv: RelevantDef, span: span) -> Variable { match rv { - RelevantSelf => self.s.self_var, RelevantVar(nid) => self.variable(nid, span) } } @@ -934,14 +898,6 @@ impl Liveness { } } - // as above, the "self" variable is a non-owned variable - self.acc(self.s.exit_ln, self.s.self_var, ACC_READ); - - // in a ctor, there is an implicit use of self.f for all fields f: - for self.ir.field_map.each_value |var| { - self.acc(self.s.exit_ln, var, ACC_READ|ACC_USE); - } - // the fallthrough exit is only for those cases where we do not // explicitly return: self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln); @@ -1023,24 +979,11 @@ impl Liveness { // Interesting cases with control flow or which gen/kill expr_path(_) => { - self.access_path(expr, succ, ACC_READ | ACC_USE) + self.access_path(expr, succ, ACC_READ | ACC_USE) } - expr_field(e, nm, _) => { - // If this is a reference to `self.f` inside of a ctor, - // then we treat it as a read of that variable. - // Otherwise, we ignore it and just propagate down to - // process `e`. - match self.as_self_field(e, nm) { - Some((ln, var)) => { - self.init_from_succ(ln, succ); - self.acc(ln, var, ACC_READ | ACC_USE); - ln - } - None => { - self.propagate_through_expr(e, succ) - } - } + expr_field(e, _, _) => { + self.propagate_through_expr(e, succ) } expr_fn(*) | expr_fn_block(*) => { @@ -1269,8 +1212,8 @@ impl Liveness { // In general, the full flow graph structure for an // assignment/move/etc can be handled in one of two ways, // depending on whether what is being assigned is a "tracked - // value" or not. A tracked value is basically a local variable - // or argument, or a self-field (`self.f`) in a ctor. + // value" or not. A tracked value is basically a local + // variable or argument. // // The two kinds of graphs are: // @@ -1293,12 +1236,11 @@ impl Liveness { // // # Tracked lvalues // - // A tracked lvalue is either a local variable/argument `x` or - // else it is a self-field `self.f` in a constructor. In + // A tracked lvalue is a local variable/argument `x`. In // these cases, the link_node where the write occurs is linked - // to node id of `x` or `self`, respectively. The - // `write_lvalue()` routine generates the contents of this - // node. There are no subcomponents to consider. + // to node id of `x`. The `write_lvalue()` routine generates + // the contents of this node. There are no subcomponents to + // consider. // // # Non-tracked lvalues // @@ -1315,12 +1257,9 @@ impl Liveness { // just ignore such cases and treat them as reads. match expr.node { - expr_path(_) => succ, - expr_field(e, nm, _) => match self.as_self_field(e, nm) { - Some(_) => succ, - None => self.propagate_through_expr(e, succ) - }, - _ => self.propagate_through_expr(expr, succ) + expr_path(_) => succ, + expr_field(e, _, _) => self.propagate_through_expr(e, succ), + _ => self.propagate_through_expr(expr, succ) } } @@ -1330,14 +1269,6 @@ impl Liveness { acc: uint) -> LiveNode { match expr.node { expr_path(_) => self.access_path(expr, succ, acc), - expr_field(e, nm, _) => match self.as_self_field(e, nm) { - Some((ln, var)) => { - self.init_from_succ(ln, succ); - self.acc(ln, var, acc); - ln - } - None => succ - }, // We do not track other lvalues, so just propagate through // to their subcomponents. Also, it may happen that @@ -1350,26 +1281,6 @@ impl Liveness { fn access_path(expr: @expr, succ: LiveNode, acc: uint) -> LiveNode { let def = self.tcx.def_map.get(expr.id); match relevant_def(def) { - Some(RelevantSelf) => { - // Accessing `self` is like accessing every field of - // the current object. This allows something like - // `self = ...;` (it will be considered a write to - // every field, sensibly enough), though the borrowck - // pass will reject it later on. - // - // Also, note that, within a ctor at least, an - // expression like `self.f` is "shortcircuiting" - // before it reaches this point by the code for - // expr_field. - let ln = self.live_node(expr.id, expr.span); - if acc != 0u { - self.init_from_succ(ln, succ); - for self.ir.field_map.each_value |var| { - self.acc(ln, var, acc); - } - } - ln - } Some(RelevantVar(nid)) => { let ln = self.live_node(expr.id, expr.span); if acc != 0u { @@ -1383,29 +1294,6 @@ impl Liveness { } } - fn as_self_field(expr: @expr, - fld: ident) -> Option<(LiveNode,Variable)> { - // If we checking a constructor, then we treat self.f as a - // variable. we use the live_node id that will be assigned to - // the reference to self but the variable id for `f`. - match expr.node { - expr_path(_) => { - let def = self.tcx.def_map.get(expr.id); - match def { - def_self(_) => { - // Note: the field_map is empty unless we are in a ctor - return self.ir.field_map.find(fld).map(|var| { - let ln = self.live_node(expr.id, expr.span); - (ln, *var) - }); - } - _ => return None - } - } - _ => return None - } - } - fn propagate_through_loop(expr: @expr, cond: Option<@expr>, body: blk, @@ -1613,24 +1501,7 @@ enum ReadKind { } impl @Liveness { - fn check_fields(sp: span, entry_ln: LiveNode) { - for self.ir.field_map.each |nm, var| { - match self.live_on_entry(entry_ln, var) { - None => { /* ok */ } - Some(ExitNode) => { - self.tcx.sess.span_err( - sp, fmt!("field `self.%s` is never initialized", - self.tcx.sess.str_of(nm))); - } - Some(lnk) => { - self.report_illegal_read( - sp, lnk, var, PossiblyUninitializedField); - } - } - } - } - - fn check_ret(id: node_id, sp: span, fk: visit::fn_kind, + fn check_ret(id: node_id, sp: span, _fk: visit::fn_kind, entry_ln: LiveNode) { if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { // if no_ret_var is live, then we fall off the end of the @@ -1644,15 +1515,8 @@ impl @Liveness { self.tcx.sess.span_err( sp, ~"some control paths may return"); } else { - match fk { - visit::fk_ctor(*) => { - // ctors are written as though they are unit. - } - _ => { - self.tcx.sess.span_err( - sp, ~"not all control paths return a value"); - } - } + self.tcx.sess.span_err( + sp, ~"not all control paths return a value"); } } } @@ -1737,7 +1601,6 @@ impl @Liveness { let var = self.variable(nid, expr.span); self.warn_about_dead_assign(expr.span, ln, var); } - Some(RelevantSelf) => {} None => {} } } @@ -1796,13 +1659,6 @@ impl @Liveness { copy or move mode", self.tcx.sess.str_of(name))); return; } - Field(name) => { - self.tcx.sess.span_err( - move_span, - fmt!("illegal move from field `%s`", - self.tcx.sess.str_of(name))); - return; - } Self => { self.tcx.sess.span_err( move_span, diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index ff708b7f4efa..eb0bf8796f07 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -305,16 +305,16 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visitor: visit::vt) { let fn_cx = match fk { - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => { - // Top-level functions are a root scope. - ctxt {parent: Some(id),.. cx} - } + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => { + // Top-level functions are a root scope. + ctxt {parent: Some(id),.. cx} + } - visit::fk_anon(*) | visit::fk_fn_block(*) => { - // Closures continue with the inherited scope. - cx - } + visit::fk_anon(*) | visit::fk_fn_block(*) => { + // Closures continue with the inherited scope. + cx + } }; debug!("visiting fn with body %d. cx.parent: %? \ @@ -641,7 +641,7 @@ fn determine_rp_in_ty(ty: @ast::ty, match ty.node { ast::ty_path(path, id) => { match cx.def_map.get(id) { - ast::def_ty(did) | ast::def_class(did, _) => { + ast::def_ty(did) | ast::def_class(did) => { if did.crate == ast::local_crate { if cx.opt_region_is_relevant(path.rp) { cx.add_dep(did.node); diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 5f30346a28e8..b455cc257ef1 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -757,7 +757,7 @@ struct Resolver { unused_import_lint_level: level, trait_info: HashMap>, - structs: HashMap, + structs: HashMap, // The number of imports that are currently unresolved. mut unresolved_imports: uint, @@ -1069,36 +1069,15 @@ impl Resolver { } // These items live in both the type and value namespaces. - item_class(struct_definition, _) => { - let new_parent = - match struct_definition.ctor { - None => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[TypeNS], sp); + item_class(*) => { + let (name_bindings, new_parent) = + self.add_child(ident, parent, ~[TypeNS], sp); - (*name_bindings).define_type - (privacy, def_ty(local_def(item.id)), sp); - new_parent - } - Some(ctor) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[ValueNS, TypeNS], - sp); - - (*name_bindings).define_type - (privacy, def_ty(local_def(item.id)), sp); - - let purity = impure_fn; - let ctor_def = def_fn(local_def(ctor.node.id), - purity); - (*name_bindings).define_value(privacy, ctor_def, sp); - new_parent - } - }; + (*name_bindings).define_type + (privacy, def_ty(local_def(item.id)), sp); // Record the def ID of this struct. - self.structs.insert(local_def(item.id), - struct_definition.ctor.is_some()); + self.structs.insert(local_def(item.id), ()); visit_item(item, new_parent, visitor); } @@ -1183,7 +1162,7 @@ impl Resolver { def_variant(item_id, local_def(variant.node.id)), variant.span); - self.structs.insert(local_def(variant.node.id), false); + self.structs.insert(local_def(variant.node.id), ()); } enum_variant_kind(enum_definition) => { (*child).define_type(privacy, @@ -1520,18 +1499,12 @@ impl Resolver { child_name_bindings.define_type(Public, def, dummy_sp()); } - def_class(def_id, has_constructor) => { + def_class(def_id) => { debug!("(building reduced graph for external \ - crate) building type %s (value? %d)", - final_ident, - if has_constructor { 1 } else { 0 }); + crate) building type %s", + final_ident); child_name_bindings.define_type(Public, def, dummy_sp()); - - if has_constructor { - child_name_bindings.define_value(Public, def, dummy_sp()); - } - - self.structs.insert(def_id, has_constructor); + self.structs.insert(def_id, ()); } def_self(*) | def_arg(*) | def_local(*) | def_prim_ty(*) | def_ty_param(*) | def_binding(*) | @@ -3306,7 +3279,6 @@ impl Resolver { struct_def.traits, struct_def.fields, struct_def.methods, - struct_def.ctor, struct_def.dtor, visitor); } @@ -3548,7 +3520,6 @@ impl Resolver { traits: ~[@trait_ref], fields: ~[@struct_field], methods: ~[@method], - optional_constructor: Option, optional_destructor: Option, visitor: ResolveVisitor) { @@ -3600,23 +3571,6 @@ impl Resolver { self.resolve_type(field.node.ty, visitor); } - // Resolve the constructor, if applicable. - match optional_constructor { - None => { - // Nothing to do. - } - Some(constructor) => { - self.resolve_function(NormalRibKind, - Some(@constructor.node.dec), - NoTypeParameters, - constructor.node.body, - HasSelfBinding(constructor.node. - self_id), - NoCaptureClause, - visitor); - } - } - // Resolve the destructor, if applicable. match optional_destructor { None => { @@ -4089,9 +4043,7 @@ impl Resolver { match self.resolve_path(path, TypeNS, false, visitor) { Some(def_ty(class_id)) if self.structs.contains_key(class_id) => { - let has_constructor = self.structs.get(class_id); - let class_def = def_class(class_id, - has_constructor); + let class_def = def_class(class_id); self.record_def(pattern.id, class_def); } Some(definition @ def_variant(_, variant_id)) @@ -4559,10 +4511,9 @@ impl Resolver { // let bar = Bar { ... } // no type parameters match self.resolve_path(path, TypeNS, false, visitor) { - Some(def_ty(class_id)) | Some(def_class(class_id, _)) + Some(def_ty(class_id)) | Some(def_class(class_id)) if self.structs.contains_key(class_id) => { - let has_constructor = self.structs.get(class_id); - let class_def = def_class(class_id, has_constructor); + let class_def = def_class(class_id); self.record_def(expr.id, class_def); } Some(definition @ def_variant(_, class_id)) diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 95711f8da36a..c605fe398734 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1596,18 +1596,14 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, // translation calls that don't have a return value (trans_crate, // trans_mod, trans_item, et cetera) and those that do // (trans_block, trans_expr, et cetera). - - if !ccx.class_ctors.contains_key(id) // hack -- - /* avoids the need for special cases to assign a type to - the constructor body (since it has no explicit return) */ - && - (body.node.expr.is_none() || - ty::type_is_bot(block_ty) || - ty::type_is_nil(block_ty)) { + if body.node.expr.is_none() || ty::type_is_bot(block_ty) || + ty::type_is_nil(block_ty) + { bcx = controlflow::trans_block(bcx, body, expr::Ignore); } else { bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr)); } + finish(bcx); cleanup_and_Br(bcx, bcx_top, fcx.llreturn); @@ -1698,60 +1694,6 @@ fn trans_enum_variant(ccx: @crate_ctxt, finish_fn(fcx, lltop); } -fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, - body: ast::blk, llctor_decl: ValueRef, - psubsts: param_substs, ctor_id: ast::node_id, - parent_id: ast::def_id, sp: span) { - // Add ctor to the ctor map - ccx.class_ctors.insert(ctor_id, parent_id); - - // Translate the ctor - - // Set up the type for the result of the ctor - // kludgy -- this wouldn't be necessary if the typechecker - // special-cased constructors, then we could just look up - // the ctor's return type. - let rslt_ty = ty::mk_class(ccx.tcx, parent_id, - dummy_substs(psubsts.tys)); - - // Make the fn context - let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, - Some(psubsts), Some(sp)); - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, decl.inputs); - let mut bcx_top = top_scope_block(fcx, body.info()); - let lltop = bcx_top.llbb; - let arg_tys = ty::ty_fn_args(node_id_type(bcx_top, ctor_id)); - bcx_top = copy_args_to_allocas(fcx, bcx_top, decl.inputs, - raw_llargs, arg_tys); - - // Create a temporary for `self` that we will return at the end - let selfdatum = datum::scratch_datum(bcx_top, rslt_ty, true); - - // Initialize dtor flag (if any) to 1 - if ty::ty_dtor(bcx_top.tcx(), parent_id).is_some() { - let flag = GEPi(bcx_top, selfdatum.val, [0, 1]); - Store(bcx_top, C_u8(1), flag); - } - - // initialize fields to zero - let mut bcx = bcx_top; - - // note we don't want to take *or* drop self. - fcx.llself = Some(ValSelfData {v: selfdatum.val, - t: rslt_ty, - is_owned: false}); - - // Translate the body of the ctor - bcx = controlflow::trans_block(bcx, body, expr::Ignore); - - // Generate the return expression - bcx = selfdatum.move_to(bcx, datum::INIT, fcx.llretptr); - - cleanup_and_leave(bcx, None, Some(fcx.llreturn)); - Unreachable(bcx); - finish_fn(fcx, lltop); -} - fn trans_class_dtor(ccx: @crate_ctxt, path: path, body: ast::blk, dtor_id: ast::node_id, psubsts: Option, @@ -1921,14 +1863,6 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, tps: ~[ast::ty_param], path: @ast_map::path, ident: ast::ident, id: ast::node_id) { if tps.len() == 0u { - let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps), - vtables: None, - bounds: @~[]}; - do option::iter(&struct_def.ctor) |ctor| { - trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body, - get_item_val(ccx, ctor.node.id), psubsts, - ctor.node.id, local_def(id), ctor.span); - } do option::iter(&struct_def.dtor) |dtor| { trans_class_dtor(ccx, *path, dtor.node.body, dtor.node.id, None, None, local_def(id)); @@ -2184,10 +2118,6 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { } } } - ast_map::node_ctor(nm, _, ctor, _, pt) => { - let my_path = vec::append(*pt, ~[path_name(nm)]); - register_fn(ccx, ctor.span, my_path, ctor.node.id) - } ast_map::node_dtor(_, dt, parent_id, pt) => { /* Don't just call register_fn, since we don't want to add @@ -2712,7 +2642,6 @@ fn trans_crate(sess: session::session, crate_map: crate_map, mut uses_gc: false, dbg_cx: dbg_cx, - class_ctors: HashMap(), mut do_not_commit_warning_issued: false}; diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 68e957bfe709..b87d690a1c34 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -170,11 +170,6 @@ type crate_ctxt = { // is not emitted by LLVM's GC pass when no functions use GC. mut uses_gc: bool, dbg_cx: Option, - // Mapping from class constructors to parent class -- - // used in base::trans_closure - // parent_class must be a def_id because ctors can be - // inlined, so the parent may be in a different crate - class_ctors: HashMap, mut do_not_commit_warning_issued: bool}; // Types used for llself. diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs index 6cd4b49fa3b3..068ec49d6c7e 100644 --- a/src/rustc/middle/trans/debuginfo.rs +++ b/src/rustc/middle/trans/debuginfo.rs @@ -732,10 +732,6 @@ fn create_function(fcx: fn_ctxt) -> @metadata { ast_map::node_method(method, _, _) => { (method.ident, method.decl.output, method.id) } - ast_map::node_ctor(nm, _, ctor, _, _) => { - // FIXME: output type may be wrong (#2194) - (nm, ctor.node.dec.output, ctor.node.id) - } ast_map::node_expr(expr) => { match expr.node { ast::expr_fn(_, decl, _, _) => { diff --git a/src/rustc/middle/trans/inline.rs b/src/rustc/middle/trans/inline.rs index 76888471bf97..ce9088d4b55c 100644 --- a/src/rustc/middle/trans/inline.rs +++ b/src/rustc/middle/trans/inline.rs @@ -34,10 +34,6 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) trans_item(ccx, *item); local_def(item.id) } - csearch::found(ast::ii_ctor(ctor, _, _, _)) => { - ccx.external.insert(fn_id, Some(ctor.node.id)); - local_def(ctor.node.id) - } csearch::found(ast::ii_foreign(item)) => { ccx.external.insert(fn_id, Some(item.id)); local_def(item.id) diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 17eaf591c9f3..32a581454d3d 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -5,7 +5,7 @@ use syntax::ast_map::{path, path_mod, path_name}; use base::{trans_item, get_item_val, no_self, self_arg, trans_fn, impl_self, decl_internal_cdecl_fn, set_inline_hint_if_appr, set_inline_hint, - trans_enum_variant, trans_class_ctor, trans_class_dtor, + trans_enum_variant, trans_class_dtor, get_insn_ctxt}; use syntax::parse::token::special_idents; use type_of::type_of_fn_from_ty; @@ -71,7 +71,6 @@ fn monomorphic_fn(ccx: @crate_ctxt, return {val: get_item_val(ccx, fn_id.node), must_cast: true}; } - ast_map::node_ctor(nm, _, ct, _, pt) => (pt, nm, ct.span), ast_map::node_dtor(_, dtor, _, pt) => (pt, special_idents::dtor, dtor.span), ast_map::node_trait_method(*) => { @@ -162,16 +161,6 @@ fn monomorphic_fn(ccx: @crate_ctxt, meth::trans_method(ccx, pt, mth, psubsts, None, d); d } - ast_map::node_ctor(_, tps, ctor, parent_id, _) => { - // ctors don't have attrs, at least not right now - let d = mk_lldecl(); - let tp_tys = ty::ty_params_to_tys(ccx.tcx, tps); - trans_class_ctor(ccx, pt, ctor.node.dec, ctor.node.body, d, - option::get_default(&psubsts, - {tys:tp_tys, vtables: None, bounds: @~[]}), - fn_id.node, parent_id, ctor.span); - d - } ast_map::node_dtor(_, dtor, _, pt) => { let parent_id = match ty::ty_to_def_id(ty::node_id_to_type(ccx.tcx, dtor.node.self_id)) { diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs index 3c4439c918fb..bfb8de76a6c5 100644 --- a/src/rustc/middle/trans/reachable.rs +++ b/src/rustc/middle/trans/reachable.rs @@ -59,10 +59,6 @@ fn traverse_def_id(cx: ctx, did: def_id) { cx.rmap.insert(item.id, ()); } ast_map::node_variant(v, _, _) => { cx.rmap.insert(v.node.id, ()); } - // If it's a ctor, consider the parent reachable - ast_map::node_ctor(_, _, _, parent_id, _) => { - traverse_def_id(cx, parent_id); - } _ => () } } @@ -104,13 +100,6 @@ fn traverse_public_item(cx: ctx, item: @item) { } } item_class(struct_def, tps) => { - do option::iter(&struct_def.ctor) |ctor| { - cx.rmap.insert(ctor.node.id, ()); - if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs) - != attr::ia_none { - traverse_inline_body(cx, ctor.node.body); - } - } do option::iter(&struct_def.dtor) |dtor| { cx.rmap.insert(dtor.node.id, ()); if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs) diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index ee247eb5db79..1f9ad20dd03e 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -109,9 +109,6 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;} } } - ast_map::node_ctor(_, _, ctor, _, _) => { - handle_body(cx, ctor.node.body); - } ast_map::node_dtor(_, dtor, _, _) => { handle_body(cx, dtor.node.body); } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index bbc3a06fb675..ff916d55b6ff 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -3318,7 +3318,7 @@ fn note_and_explain_type_err(cx: ctxt, err: &type_err) { fn def_has_ty_params(def: ast::def) -> bool { match def { - ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_, _) + ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_) => true, _ => false } @@ -3492,9 +3492,6 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path { ast_map::path_name(variant.node.name)) } - ast_map::node_ctor(nm, _, _, _, path) => { - vec::append_one(*path, ast_map::path_name(nm)) - } ast_map::node_dtor(_, _, _, path) => { vec::append_one(*path, ast_map::path_name( syntax::parse::token::special_idents::literally_dtor)) diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index 14797fcdd6bb..389c1adb016b 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -323,7 +323,7 @@ fn ast_ty_to_ty( Some(d) => d }; match a_def { - ast::def_ty(did) | ast::def_class(did, _) => { + ast::def_ty(did) | ast::def_class(did) => { ast_path_to_ty(self, rscope, did, path, id).ty } ast::def_prim_ty(nty) => { diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 7cc2c8b0ad76..1d921497ccf4 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -451,18 +451,6 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, let tcx = ccx.tcx; let self_ty = ty::node_id_to_type(tcx, id); - do option::iter(&struct_def.ctor) |ctor| { - let class_t = {self_ty: self_ty, - self_id: ctor.node.self_id, - def_id: local_def(id), - explicit_self: {node: ast::sty_by_ref, - span: ast_util::dummy_sp()}}; - // typecheck the ctor - check_bare_fn(ccx, ctor.node.dec, - ctor.node.body, ctor.node.id, - Some(class_t)); - } - do option::iter(&struct_def.dtor) |dtor| { let class_t = {self_ty: self_ty, self_id: dtor.node.self_id, @@ -1925,7 +1913,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Resolve the path. let class_id; match tcx.def_map.find(id) { - Some(ast::def_class(type_def_id, _)) => { + Some(ast::def_class(type_def_id)) => { class_id = type_def_id; } _ => { @@ -2412,7 +2400,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> ast::def_fn(id, _) | ast::def_static_method(id, _) | ast::def_const(id) | ast::def_variant(_, id) | - ast::def_class(id, _) => { + ast::def_class(id) => { return ty::lookup_item_type(fcx.ccx.tcx, id); } ast::def_upvar(_, inner, _, _) => { diff --git a/src/rustc/middle/typeck/check/alt.rs b/src/rustc/middle/typeck/check/alt.rs index 0b2e9c8ab3dd..24bcc2281fb9 100644 --- a/src/rustc/middle/typeck/check/alt.rs +++ b/src/rustc/middle/typeck/check/alt.rs @@ -325,7 +325,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { // Check to ensure that the struct is the one specified. match tcx.def_map.get(pat.id) { - ast::def_class(supplied_def_id, _) + ast::def_class(supplied_def_id) if supplied_def_id == class_id => { // OK. } diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 18e29981af30..472c8a30459d 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -497,30 +497,6 @@ fn convert_struct(ccx: @crate_ctxt, tpt: ty::ty_param_bounds_and_ty, id: ast::node_id) { let tcx = ccx.tcx; - do option::iter(&struct_def.ctor) |ctor| { - // Write the ctor type - let t_args = ctor.node.dec.inputs.map( - |a| ty_of_arg(ccx, type_rscope(rp), *a, None) ); - let t_res = ty::mk_class( - tcx, local_def(id), - {self_r: rscope::bound_self_region(rp), - self_ty: None, - tps: ty::ty_params_to_tys(tcx, tps)}); - let proto = ty::proto_vstore(ty::vstore_slice(ty::re_static)); - let t_ctor = ty::mk_fn(tcx, FnTyBase { - meta: FnMeta {purity: ast::impure_fn, - proto: proto, - bounds: @~[], - ret_style: ast::return_val}, - sig: FnSig {inputs: t_args, - output: t_res} - }); - write_ty_to_tcx(tcx, ctor.node.id, t_ctor); - tcx.tcache.insert(local_def(ctor.node.id), - {bounds: tpt.bounds, - region_param: rp, - ty: t_ctor}); - } do option::iter(&struct_def.dtor) |dtor| { // Write the dtor type diff --git a/src/test/compile-fail/issue-2590.rs b/src/test/compile-fail/issue-2590.rs index f4ccd901fb3a..0f4a4804c751 100644 --- a/src/test/compile-fail/issue-2590.rs +++ b/src/test/compile-fail/issue-2590.rs @@ -10,7 +10,7 @@ trait parse { impl parser: parse { fn parse() -> ~[int] { - dvec::unwrap(move self.tokens) //~ ERROR illegal move from self + dvec::unwrap(move self.tokens) //~ ERROR moving out of immutable field } } diff --git a/src/test/compile-fail/regions-glb-free-free.rs b/src/test/compile-fail/regions-glb-free-free.rs index 223665381da1..e4913f7056e8 100644 --- a/src/test/compile-fail/regions-glb-free-free.rs +++ b/src/test/compile-fail/regions-glb-free-free.rs @@ -19,7 +19,7 @@ mod argparse { fn set_desc(self, s: &str) -> Flag { Flag { //~ ERROR cannot infer an appropriate lifetime name: self.name, - desc: s, + desc: s, //~ ERROR cannot infer an appropriate lifetime max_count: self.max_count, value: self.value } From bb1ed97ca2bbd8efa1555462de3f842d702e8408 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 8 Oct 2012 08:06:25 -0700 Subject: [PATCH 022/292] libcore: str trim functions can be applied to &strs --- src/libcore/str.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 285b61149577..d7d33b5528b5 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2195,6 +2195,16 @@ impl &str: StrSlice { #[inline] fn escape_unicode() -> ~str { escape_unicode(self) } + /// Returns a string with leading and trailing whitespace removed + #[inline] + fn trim() -> ~str { trim(self) } + /// Returns a string with leading whitespace removed + #[inline] + fn trim_left() -> ~str { trim_left(self) } + /// Returns a string with trailing whitespace removed + #[inline] + fn trim_right() -> ~str { trim_right(self) } + #[inline] pure fn to_unique() -> ~str { self.slice(0, self.len()) } From 79603f573e504163db7b5c2afa0917c27e3f98ed Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 8 Oct 2012 08:17:41 -0700 Subject: [PATCH 023/292] libcore: include the trim methods in the StrSlice trait --- src/libcore/str.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d7d33b5528b5..d743f0c7f3be 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2086,6 +2086,9 @@ pub trait StrSlice { pure fn to_upper() -> ~str; fn escape_default() -> ~str; fn escape_unicode() -> ~str; + fn trim() -> ~str; + fn trim_left() -> ~str; + fn trim_right() -> ~str; pure fn to_unique() -> ~str; pure fn char_at(i: uint) -> char; } From bbda995bfe03680b6d621c6ab809ddb145125c3a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Oct 2012 08:38:03 -0700 Subject: [PATCH 024/292] cap-clause-use-after-move: modernize error msg --- src/test/compile-fail/cap-clause-use-after-move.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/compile-fail/cap-clause-use-after-move.rs b/src/test/compile-fail/cap-clause-use-after-move.rs index 7fb06ba5a23a..6946419ac9cd 100644 --- a/src/test/compile-fail/cap-clause-use-after-move.rs +++ b/src/test/compile-fail/cap-clause-use-after-move.rs @@ -1,7 +1,5 @@ -// error-pattern:Unsatisfied precondition constraint - fn main() { let x = 5; let _y = fn~(move x) { }; - let _z = x; //< error: Unsatisfied precondition constraint + let _z = x; //~ ERROR use of moved variable: `x` } From 7bdab1e4a45bf734e4b25a2d58f4ee21ee5c9fdc Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 09:00:23 -0700 Subject: [PATCH 025/292] Revert "remove ctor from ast" This reverts commit ed3689d57c988e1dd477930d957c4308c37d1a64. --- src/libsyntax/ast.rs | 9 +- src/libsyntax/ast_map.rs | 20 +- src/libsyntax/ast_util.rs | 13 +- src/libsyntax/fold.rs | 19 ++ src/libsyntax/parse/parser.rs | 65 +++++- src/libsyntax/print/pprust.rs | 12 ++ src/libsyntax/visit.rs | 33 ++- src/rustc/metadata/decoder.rs | 6 +- src/rustc/metadata/encoder.rs | 22 +- src/rustc/middle/astencode.rs | 23 +- src/rustc/middle/borrowck/check_loans.rs | 60 ++++-- src/rustc/middle/borrowck/gather_loans.rs | 10 +- src/rustc/middle/kind.rs | 6 +- src/rustc/middle/liveness.rs | 202 +++++++++++++++--- src/rustc/middle/region.rs | 20 +- src/rustc/middle/resolve.rs | 79 +++++-- src/rustc/middle/trans/base.rs | 79 ++++++- src/rustc/middle/trans/common.rs | 5 + src/rustc/middle/trans/debuginfo.rs | 4 + src/rustc/middle/trans/inline.rs | 4 + src/rustc/middle/trans/monomorphize.rs | 13 +- src/rustc/middle/trans/reachable.rs | 11 + src/rustc/middle/trans/type_use.rs | 3 + src/rustc/middle/ty.rs | 5 +- src/rustc/middle/typeck/astconv.rs | 2 +- src/rustc/middle/typeck/check.rs | 16 +- src/rustc/middle/typeck/check/alt.rs | 2 +- src/rustc/middle/typeck/collect.rs | 24 +++ src/test/compile-fail/issue-2590.rs | 2 +- .../compile-fail/regions-glb-free-free.rs | 2 +- 30 files changed, 651 insertions(+), 120 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ced64daa8d61..1c279f81cc39 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -135,7 +135,7 @@ enum def { @def, // closed over def node_id, // expr node that creates the closure node_id), // id for the block/body of the closure expr - def_class(def_id), + def_class(def_id, bool /* has constructor */), def_typaram_binder(node_id), /* class, impl or trait that has ty params */ def_region(node_id), def_label(node_id) @@ -235,9 +235,9 @@ impl def : cmp::Eq { _ => false } } - def_class(e0a) => { + def_class(e0a, e1a) => { match (*other) { - def_class(e0b) => e0a == e0b, + def_class(e0b, e1b) => e0a == e0b && e1a == e1b, _ => false } } @@ -1462,6 +1462,8 @@ type struct_def = { fields: ~[@struct_field], /* fields */ methods: ~[@method], /* methods */ /* (not including ctor or dtor) */ + /* ctor is optional, and will soon go away */ + ctor: Option, /* dtor is optional */ dtor: Option }; @@ -1561,6 +1563,7 @@ enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), ii_foreign(@foreign_item), + ii_ctor(class_ctor, ident, ~[ty_param], def_id /* parent id */), ii_dtor(class_dtor, ident, ~[ty_param], def_id /* parent id */) } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 8555ceed2dbd..d05c6eadaf6a 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -71,6 +71,9 @@ enum ast_node { // order they are introduced. node_arg(arg, uint), node_local(uint), + // Constructor for a class + // def_id is parent id + node_ctor(ident, ~[ty_param], @class_ctor, def_id, @path), // Destructor for a class node_dtor(~[ty_param], @class_dtor, def_id, @path), node_block(blk), @@ -129,7 +132,7 @@ fn map_decoded_item(diag: span_handler, // don't decode and instantiate the impl, but just the method, we have to // add it to the table now: match ii { - ii_item(*) | ii_dtor(*) => { /* fallthrough */ } + ii_item(*) | ii_ctor(*) | ii_dtor(*) => { /* fallthrough */ } ii_foreign(i) => { cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic, @path)); @@ -152,6 +155,18 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, cx.local_id += 1u; } match fk { + visit::fk_ctor(nm, attrs, tps, self_id, parent_id) => { + let ct = @{node: {id: id, + attrs: attrs, + self_id: self_id, + dec: /* FIXME (#2543) */ copy decl, + body: /* FIXME (#2543) */ copy body}, + span: sp}; + cx.map.insert(id, node_ctor(/* FIXME (#2543) */ copy nm, + /* FIXME (#2543) */ copy tps, + ct, parent_id, + @/* FIXME (#2543) */ copy cx.path)); + } visit::fk_dtor(tps, attrs, self_id, parent_id) => { let dt = @{node: {id: id, attrs: attrs, self_id: self_id, body: /* FIXME (#2543) */ copy body}, span: sp}; @@ -367,6 +382,9 @@ fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { Some(node_local(_)) => { // add more info here fmt!("local (id=%?)", id) } + Some(node_ctor(*)) => { // add more info here + fmt!("node_ctor (id=%?)", id) + } Some(node_dtor(*)) => { // add more info here fmt!("node_dtor (id=%?)", id) } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 9e44c42a7027..47cbdb7ac6cb 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -57,7 +57,7 @@ pure fn def_id_of_def(d: def) -> def_id { def_fn(id, _) | def_static_method(id, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | - def_use(id) | def_class(id) => { + def_use(id) | def_class(id, _) => { id } def_arg(id, _) | def_local(id, _) | def_self(id) | @@ -339,6 +339,7 @@ impl inlined_item: inlined_item_utils { ii_item(i) => /* FIXME (#2543) */ copy i.ident, ii_foreign(i) => /* FIXME (#2543) */ copy i.ident, ii_method(_, m) => /* FIXME (#2543) */ copy m.ident, + ii_ctor(_, nm, _, _) => /* FIXME (#2543) */ copy nm, ii_dtor(_, nm, _, _) => /* FIXME (#2543) */ copy nm } } @@ -348,6 +349,7 @@ impl inlined_item: inlined_item_utils { ii_item(i) => i.id, ii_foreign(i) => i.id, ii_method(_, m) => m.id, + ii_ctor(ctor, _, _, _) => ctor.node.id, ii_dtor(dtor, _, _, _) => dtor.node.id } } @@ -357,6 +359,9 @@ impl inlined_item: inlined_item_utils { ii_item(i) => v.visit_item(i, e, v), ii_foreign(i) => v.visit_foreign_item(i, e, v), ii_method(_, m) => visit::visit_method_helper(m, e, v), + ii_ctor(ctor, nm, tps, parent_id) => { + visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v); + } ii_dtor(dtor, _, tps, parent_id) => { visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v); } @@ -490,6 +495,12 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { vfn(id); match fk { + visit::fk_ctor(_, _, tps, self_id, parent_id) => { + for vec::each(tps) |tp| { vfn(tp.id); } + vfn(id); + vfn(self_id); + vfn(parent_id.node); + } visit::fk_dtor(tps, _, self_id, parent_id) => { for vec::each(tps) |tp| { vfn(tp.id); } vfn(id); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 68d9cd80430d..088df01985ee 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -271,6 +271,23 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold) -> @ast::struct_def { + let resulting_optional_constructor; + match struct_def.ctor { + None => { + resulting_optional_constructor = None; + } + Some(constructor) => { + resulting_optional_constructor = Some({ + node: { + body: fld.fold_block(constructor.node.body), + dec: fold_fn_decl(constructor.node.dec, fld), + id: fld.new_id(constructor.node.id), + .. constructor.node + }, + .. constructor + }); + } + } let dtor = do option::map(&struct_def.dtor) |dtor| { let dtor_body = fld.fold_block(dtor.node.body); let dtor_id = fld.new_id(dtor.node.id); @@ -281,6 +298,7 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold) traits: vec::map(struct_def.traits, |p| fold_trait_ref(*p, fld)), fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)), methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)), + ctor: resulting_optional_constructor, dtor: dtor }; } @@ -567,6 +585,7 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { |f| fld.fold_struct_field(*f)), methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)), + ctor: None, dtor: dtor }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f2e17c0a7e63..22c25186c918 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -115,7 +115,8 @@ enum class_member { So that we can distinguish a class ctor or dtor from other class members */ -enum class_contents { dtor_decl(blk, ~[attribute], codemap::span), +enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span), + dtor_decl(blk, ~[attribute], codemap::span), members(~[@class_member]) } type arg_or_capture_item = Either; @@ -2682,13 +2683,30 @@ impl parser { let mut fields: ~[@struct_field]; let mut methods: ~[@method] = ~[]; + let mut the_ctor: Option<(fn_decl, ~[attribute], blk, codemap::span)> + = None; let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None; + let ctor_id = self.get_id(); if self.eat(token::LBRACE) { // It's a record-like struct. fields = ~[]; while self.token != token::RBRACE { match self.parse_class_item() { + ctor_decl(a_fn_decl, attrs, blk, s) => { + match the_ctor { + Some((_, _, _, s_first)) => { + self.span_note(s, #fmt("Duplicate constructor \ + declaration for class %s", + *self.interner.get(class_name))); + self.span_fatal(copy s_first, ~"First constructor \ + declared here"); + } + None => { + the_ctor = Some((a_fn_decl, attrs, blk, s)); + } + } + } dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { @@ -2746,14 +2764,36 @@ impl parser { self_id: self.get_id(), body: d_body}, span: d_s}}; - (class_name, - item_class(@{ - traits: traits, - fields: move fields, - methods: move methods, - dtor: actual_dtor - }, ty_params), - None) + match the_ctor { + Some((ct_d, ct_attrs, ct_b, ct_s)) => { + (class_name, + item_class(@{ + traits: traits, + fields: move fields, + methods: move methods, + ctor: Some({ + node: {id: ctor_id, + attrs: ct_attrs, + self_id: self.get_id(), + dec: ct_d, + body: ct_b}, + span: ct_s}), + dtor: actual_dtor + }, ty_params), + None) + } + None => { + (class_name, + item_class(@{ + traits: traits, + fields: move fields, + methods: move methods, + ctor: None, + dtor: actual_dtor + }, ty_params), + None) + } + } } fn token_is_pound_or_doc_comment(++tok: token::token) -> bool { @@ -3057,6 +3097,12 @@ impl parser { let mut methods: ~[@method] = ~[]; while self.token != token::RBRACE { match self.parse_class_item() { + ctor_decl(*) => { + self.span_fatal(copy self.span, + ~"deprecated explicit \ + constructors are not allowed \ + here"); + } dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { @@ -3097,6 +3143,7 @@ impl parser { traits: ~[], fields: move fields, methods: move methods, + ctor: None, dtor: actual_dtor }; } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b98014f421bb..bff356e5cb72 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -653,6 +653,18 @@ fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param], } bopen(s); hardbreak_if_not_bol(s); + do struct_def.ctor.iter |ctor| { + maybe_print_comment(s, ctor.span.lo); + print_outer_attributes(s, ctor.node.attrs); + // Doesn't call head because there shouldn't be a space after new. + cbox(s, indent_unit); + ibox(s, 4); + word(s.s, ~"new("); + print_fn_args(s, ctor.node.dec, ~[], None); + word(s.s, ~")"); + space(s.s); + print_block(s, ctor.node.body); + } do struct_def.dtor.iter |dtor| { hardbreak_if_not_bol(s); maybe_print_comment(s, dtor.span.lo); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 50fbd21f7b8d..e6fd65eb458a 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -17,6 +17,8 @@ enum fn_kind { fk_method(ident, ~[ty_param], @method), fk_anon(proto, capture_clause), //< an anonymous function like fn@(...) fk_fn_block(capture_clause), //< a block {||...} + fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */, + def_id /* parent class id */), // class constructor fk_dtor(~[ty_param], ~[attribute], node_id /* self id */, def_id /* parent class id */) // class destructor @@ -24,9 +26,8 @@ enum fn_kind { fn name_of_fn(fk: fn_kind) -> ident { match fk { - fk_item_fn(name, _, _) | fk_method(name, _, _) => { - /* FIXME (#2543) */ copy name - } + fk_item_fn(name, _, _) | fk_method(name, _, _) + | fk_ctor(name, _, _, _, _) => /* FIXME (#2543) */ copy name, fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon, fk_dtor(*) => parse::token::special_idents::dtor } @@ -34,11 +35,11 @@ fn name_of_fn(fk: fn_kind) -> ident { fn tps_of_fn(fk: fn_kind) -> ~[ty_param] { match fk { - fk_item_fn(_, tps, _) | fk_method(_, tps, _) | - fk_dtor(tps, _, _, _) => { - /* FIXME (#2543) */ copy tps - } - fk_anon(*) | fk_fn_block(*) => ~[] + fk_item_fn(_, tps, _) | fk_method(_, tps, _) + | fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) => { + /* FIXME (#2543) */ copy tps + } + fk_anon(*) | fk_fn_block(*) => ~[] } } @@ -290,6 +291,17 @@ fn visit_method_helper(m: @method, e: E, v: vt) { m.decl, m.body, m.span, m.id, e, v); } +// Similar logic to the comment on visit_method_helper - Tim +fn visit_class_ctor_helper(ctor: class_ctor, nm: ident, tps: ~[ty_param], + parent_id: def_id, e: E, v: vt) { + v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm, + ctor.node.attrs, + /* FIXME (#2543) */ copy tps, + ctor.node.self_id, parent_id), + ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v) + +} + fn visit_class_dtor_helper(dtor: class_dtor, tps: ~[ty_param], parent_id: def_id, e: E, v: vt) { v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs, @@ -318,7 +330,7 @@ fn visit_trait_method(m: trait_method, e: E, v: vt) { } } -fn visit_struct_def(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param], +fn visit_struct_def(sd: @struct_def, nm: ast::ident, tps: ~[ty_param], id: node_id, e: E, v: vt) { for sd.fields.each |f| { v.visit_struct_field(*f, e, v); @@ -329,6 +341,9 @@ fn visit_struct_def(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param], for sd.traits.each |p| { visit_path(p.path, e, v); } + do option::iter(&sd.ctor) |ctor| { + visit_class_ctor_helper(*ctor, nm, tps, ast_util::local_def(id), e, v); + }; do option::iter(&sd.dtor) |dtor| { visit_class_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v) }; diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 70a47522f379..197e567ab2f8 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -123,6 +123,7 @@ enum Family { Variant, // v Impl, // i Trait, // I + Class, // C Struct, // S PublicField, // g PrivateField, // j @@ -155,6 +156,7 @@ fn item_family(item: ebml2::Doc) -> Family { 'v' => Variant, 'i' => Impl, 'I' => Trait, + 'C' => Class, 'S' => Struct, 'g' => PublicField, 'j' => PrivateField, @@ -298,7 +300,8 @@ fn item_to_def_like(item: ebml2::Doc, did: ast::def_id, cnum: ast::crate_num) let fam = item_family(item); match fam { Const => dl_def(ast::def_const(did)), - Struct => dl_def(ast::def_class(did)), + Class => dl_def(ast::def_class(did, true)), + Struct => dl_def(ast::def_class(did, false)), UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), Fn => dl_def(ast::def_fn(did, ast::impure_fn)), PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), @@ -819,6 +822,7 @@ fn item_family_to_str(fam: Family) -> ~str { Variant => ~"variant", Impl => ~"impl", Trait => ~"trait", + Class => ~"class", Struct => ~"struct", PublicField => ~"public field", PrivateField => ~"private field", diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index ce3f50e71842..95696a141566 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -635,7 +635,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, /* Now, make an item for the class itself */ ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); - encode_family(ebml_w, 'S'); + + match struct_def.ctor { + None => encode_family(ebml_w, 'S'), + Some(_) => encode_family(ebml_w, 'C') + } + encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); @@ -694,6 +699,21 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml2::Serializer, let bkts = create_index(idx); encode_index(ebml_w, bkts, write_int); ebml_w.end_tag(); + + /* Encode the constructor */ + for struct_def.ctor.each |ctor| { + debug!("encoding info for ctor %s %d", + ecx.tcx.sess.str_of(item.ident), ctor.node.id); + index.push({ + val: ctor.node.id, + pos: ebml_w.writer.tell() + }); + encode_info_for_ctor(ecx, ebml_w, ctor.node.id, item.ident, + path, if tps.len() > 0u { + Some(ii_ctor(*ctor, item.ident, tps, + local_def(item.id))) } + else { None }, tps); + } } item_impl(tps, opt_trait, _, methods) => { add_to_index(); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 95c3d08f60e5..39ec58c079ed 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -262,6 +262,13 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } + ast::ii_ctor(ctor, nm, tps, parent_id) => { + let ctor_body = fld.fold_block(ctor.node.body); + let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); + ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl, + .. ctor.node}, + .. ctor}, nm, tps, parent_id) + } ast::ii_dtor(dtor, nm, tps, parent_id) => { let dtor_body = fld.fold_block(dtor.node.body); ast::ii_dtor({node: {body: dtor_body, @@ -295,6 +302,18 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } + ast::ii_ctor(ctor, nm, tps, parent_id) => { + let ctor_body = fld.fold_block(ctor.node.body); + let ctor_attrs = fld.fold_attributes(ctor.node.attrs); + let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); + let new_params = fold::fold_ty_params(tps, fld); + let ctor_id = fld.new_id(ctor.node.id); + let new_parent = xcx.tr_def_id(parent_id); + ast::ii_ctor({node: {body: ctor_body, attrs: ctor_attrs, + dec: ctor_decl, id: ctor_id, + .. ctor.node}, + .. ctor}, nm, new_params, new_parent) + } ast::ii_dtor(dtor, nm, tps, parent_id) => { let dtor_body = fld.fold_block(dtor.node.body); let dtor_attrs = fld.fold_attributes(dtor.node.attrs); @@ -350,8 +369,8 @@ impl ast::def: tr { xcx.tr_id(nid2), xcx.tr_id(nid3)) } - ast::def_class(did) => { - ast::def_class(did.tr(xcx)) + ast::def_class(did, has_constructor) => { + ast::def_class(did.tr(xcx), has_constructor) } ast::def_region(nid) => ast::def_region(xcx.tr_id(nid)), ast::def_typaram_binder(nid) => { diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index 6a9195b45096..cc8d89a8ace7 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -17,6 +17,10 @@ enum check_loan_ctxt = @{ reported: HashMap, + // Keep track of whether we're inside a ctor, so as to + // allow mutating immutable fields in the same class if + // we are in a ctor, we track the self id + mut in_ctor: bool, mut declared_purity: ast::purity, mut fn_args: @~[ast::node_id] }; @@ -58,6 +62,7 @@ fn check_loans(bccx: borrowck_ctxt, let clcx = check_loan_ctxt(@{bccx: bccx, req_maps: req_maps, reported: HashMap(), + mut in_ctor: false, mut declared_purity: ast::impure_fn, mut fn_args: @~[]}); let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr, @@ -315,7 +320,10 @@ impl check_loan_ctxt { debug!("check_assignment(cmt=%s)", self.bccx.cmt_to_repr(cmt)); - if self.is_local_variable(cmt) && at.checked_by_liveness() { + if self.in_ctor && self.is_self_field(cmt) + && at.checked_by_liveness() { + // assigning to self.foo in a ctor is always allowed. + } else if self.is_local_variable(cmt) && at.checked_by_liveness() { // liveness guarantees that immutable local variables // are only assigned once } else { @@ -534,28 +542,42 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visitor: visit::vt) { debug!("purity on entry=%?", copy self.declared_purity); - do save_and_restore(&mut(self.declared_purity)) { - do save_and_restore(&mut(self.fn_args)) { - let is_stack_closure = self.is_stack_closure(id); - let fty = ty::node_id_to_type(self.tcx(), id); - self.declared_purity = ty::determine_inherited_purity( - copy self.declared_purity, - ty::ty_fn_purity(fty), - ty::ty_fn_proto(fty)); + do save_and_restore(&mut(self.in_ctor)) { + do save_and_restore(&mut(self.declared_purity)) { + do save_and_restore(&mut(self.fn_args)) { + let is_stack_closure = self.is_stack_closure(id); + let fty = ty::node_id_to_type(self.tcx(), id); + self.declared_purity = ty::determine_inherited_purity( + copy self.declared_purity, + ty::ty_fn_purity(fty), + ty::ty_fn_proto(fty)); - match fk { - visit::fk_anon(*) | - visit::fk_fn_block(*) if is_stack_closure => { - // inherits the fn_args from enclosing ctxt - } - visit::fk_anon(*) | visit::fk_fn_block(*) | - visit::fk_method(*) | visit::fk_item_fn(*) | - visit::fk_dtor(*) => { + // In principle, we could consider fk_anon(*) or + // fk_fn_block(*) to be in a ctor, I suppose, but the + // purpose of the in_ctor flag is to allow modifications + // of otherwise immutable fields and typestate wouldn't be + // able to "see" into those functions anyway, so it + // wouldn't be very helpful. + match fk { + visit::fk_ctor(*) => { + self.in_ctor = true; self.fn_args = @decl.inputs.map(|i| i.id ); + } + visit::fk_anon(*) | + visit::fk_fn_block(*) if is_stack_closure => { + self.in_ctor = false; + // inherits the fn_args from enclosing ctxt + } + visit::fk_anon(*) | visit::fk_fn_block(*) | + visit::fk_method(*) | visit::fk_item_fn(*) | + visit::fk_dtor(*) => { + self.in_ctor = false; + self.fn_args = @decl.inputs.map(|i| i.id ); + } } - } - visit::visit_fn(fk, decl, body, sp, id, self, visitor); + visit::visit_fn(fk, decl, body, sp, id, self, visitor); + } } } debug!("purity on exit=%?", copy self.declared_purity); diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index 2a23ec86c514..5dfde8c9af64 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -71,11 +71,11 @@ fn req_loans_in_fn(fk: visit::fn_kind, self.root_ub = body.node.id; match fk { - visit::fk_anon(*) | visit::fk_fn_block(*) => {} - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_dtor(*) => { - self.item_ub = body.node.id; - } + visit::fk_anon(*) | visit::fk_fn_block(*) => {} + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_ctor(*) | visit::fk_dtor(*) => { + self.item_ub = body.node.id; + } } visit::visit_fn(fk, decl, body, sp, id, self, v); diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index 7b473cedb4c5..e2b85441a8fd 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -181,9 +181,9 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, // variables. This list is used below to avoid checking and reporting // on a given variable twice. let cap_clause = match fk { - visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc, - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_dtor(*) => @~[] + visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc, + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_ctor(*) | visit::fk_dtor(*) => @~[] }; let captured_vars = do (*cap_clause).map |cap_item| { let cap_def = cx.tcx.def_map.get(cap_item.id); diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 86f786e7706f..12d63cdacbf6 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -35,6 +35,12 @@ * Any use of the variable where the variable is dead afterwards is a * last use. * + * # Extension to handle constructors + * + * Each field is assigned an index just as with local variables. A use of + * `self` is considered a use of all fields. A use of `self.f` is just a use + * of `f`. + * * # Implementation details * * The actual implementation contains two (nested) walks over the AST. @@ -90,6 +96,8 @@ * - `no_ret_var`: a synthetic variable that is only 'read' from, the * fallthrough node. This allows us to detect functions where we fail * to return explicitly. + * + * - `self_var`: a variable representing 'self' */ use dvec::DVec; @@ -222,7 +230,7 @@ impl LiveNode { fn invalid_node() -> LiveNode { LiveNode(uint::max_value) } -enum RelevantDef { RelevantVar(node_id) } +enum RelevantDef { RelevantVar(node_id), RelevantSelf } type CaptureInfo = {ln: LiveNode, is_move: bool, rv: RelevantDef}; @@ -242,12 +250,15 @@ struct LocalInfo { enum VarKind { Arg(node_id, ident, rmode), Local(LocalInfo), + Field(ident), Self, ImplicitRet } fn relevant_def(def: def) -> Option { match def { + def_self(_) => Some(RelevantSelf), + def_binding(nid, _) | def_arg(nid, _) | def_local(nid, _) => Some(RelevantVar(nid)), @@ -265,6 +276,7 @@ struct IrMaps { mut num_vars: uint, live_node_map: HashMap, variable_map: HashMap, + field_map: HashMap, capture_map: HashMap, mut var_kinds: ~[VarKind], mut lnks: ~[LiveNodeKind], @@ -281,6 +293,7 @@ fn IrMaps(tcx: ty::ctxt, method_map: typeck::method_map, live_node_map: HashMap(), variable_map: HashMap(), capture_map: HashMap(), + field_map: HashMap(), var_kinds: ~[], lnks: ~[] } @@ -310,12 +323,15 @@ impl IrMaps { self.num_vars += 1u; match vk { - Local(LocalInfo {id:node_id, _}) | - Arg(node_id, _, _) => { - self.variable_map.insert(node_id, v); - } - Self | ImplicitRet => { - } + Local(LocalInfo {id:node_id, _}) | + Arg(node_id, _, _) => { + self.variable_map.insert(node_id, v); + } + Field(name) => { + self.field_map.insert(name, v); + } + Self | ImplicitRet => { + } } debug!("%s is %?", v.to_str(), vk); @@ -335,10 +351,11 @@ impl IrMaps { fn variable_name(var: Variable) -> ~str { match copy self.var_kinds[*var] { - Local(LocalInfo {ident: nm, _}) | - Arg(_, nm, _) => self.tcx.sess.str_of(nm), - Self => ~"self", - ImplicitRet => ~"" + Local(LocalInfo {ident: nm, _}) | + Arg(_, nm, _) => self.tcx.sess.str_of(nm), + Field(nm) => ~"self." + self.tcx.sess.str_of(nm), + Self => ~"self", + ImplicitRet => ~"" } } @@ -382,7 +399,7 @@ impl IrMaps { (*v).push(id); } Arg(_, _, by_ref) | - Arg(_, _, by_val) | Self | ImplicitRet | + Arg(_, _, by_val) | Self | Field(_) | ImplicitRet | Local(LocalInfo {kind: FromMatch(bind_by_implicit_ref), _}) => { debug!("--but it is not owned"); } @@ -411,6 +428,13 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, // and so forth: visit::visit_fn(fk, decl, body, sp, id, fn_maps, v); + match fk { + visit::fk_ctor(_, _, _, _, class_did) => { + add_class_fields(fn_maps, class_did); + } + _ => {} + } + // Special nodes and variables: // - exit_ln represents the end of the fn, either by return or fail // - implicit_ret_var is a pseudo-variable that represents @@ -418,7 +442,8 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, let specials = { exit_ln: (*fn_maps).add_live_node(ExitNode), fallthrough_ln: (*fn_maps).add_live_node(ExitNode), - no_ret_var: (*fn_maps).add_variable(ImplicitRet) + no_ret_var: (*fn_maps).add_variable(ImplicitRet), + self_var: (*fn_maps).add_variable(Self) }; // compute liveness @@ -435,9 +460,18 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, }); check_vt.visit_block(body, lsets, check_vt); lsets.check_ret(id, sp, fk, entry_ln); + lsets.check_fields(sp, entry_ln); lsets.warn_about_unused_args(sp, decl, entry_ln); } +fn add_class_fields(self: @IrMaps, did: def_id) { + for ty::lookup_class_fields(self.tcx, did).each |field_ty| { + assert field_ty.id.crate == local_crate; + let var = self.add_variable(Field(field_ty.ident)); + self.field_map.insert(field_ty.ident, var); + } +} + fn visit_local(local: @local, &&self: @IrMaps, vt: vt<@IrMaps>) { let def_map = self.tcx.def_map; do pat_util::pat_bindings(def_map, local.node.pat) |_bm, p_id, sp, path| { @@ -561,7 +595,8 @@ fn invalid_users() -> users { type Specials = { exit_ln: LiveNode, fallthrough_ln: LiveNode, - no_ret_var: Variable + no_ret_var: Variable, + self_var: Variable }; const ACC_READ: uint = 1u; @@ -614,6 +649,7 @@ impl Liveness { fn variable_from_rdef(rv: RelevantDef, span: span) -> Variable { match rv { + RelevantSelf => self.s.self_var, RelevantVar(nid) => self.variable(nid, span) } } @@ -898,6 +934,14 @@ impl Liveness { } } + // as above, the "self" variable is a non-owned variable + self.acc(self.s.exit_ln, self.s.self_var, ACC_READ); + + // in a ctor, there is an implicit use of self.f for all fields f: + for self.ir.field_map.each_value |var| { + self.acc(self.s.exit_ln, var, ACC_READ|ACC_USE); + } + // the fallthrough exit is only for those cases where we do not // explicitly return: self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln); @@ -979,11 +1023,24 @@ impl Liveness { // Interesting cases with control flow or which gen/kill expr_path(_) => { - self.access_path(expr, succ, ACC_READ | ACC_USE) + self.access_path(expr, succ, ACC_READ | ACC_USE) } - expr_field(e, _, _) => { - self.propagate_through_expr(e, succ) + expr_field(e, nm, _) => { + // If this is a reference to `self.f` inside of a ctor, + // then we treat it as a read of that variable. + // Otherwise, we ignore it and just propagate down to + // process `e`. + match self.as_self_field(e, nm) { + Some((ln, var)) => { + self.init_from_succ(ln, succ); + self.acc(ln, var, ACC_READ | ACC_USE); + ln + } + None => { + self.propagate_through_expr(e, succ) + } + } } expr_fn(*) | expr_fn_block(*) => { @@ -1212,8 +1269,8 @@ impl Liveness { // In general, the full flow graph structure for an // assignment/move/etc can be handled in one of two ways, // depending on whether what is being assigned is a "tracked - // value" or not. A tracked value is basically a local - // variable or argument. + // value" or not. A tracked value is basically a local variable + // or argument, or a self-field (`self.f`) in a ctor. // // The two kinds of graphs are: // @@ -1236,11 +1293,12 @@ impl Liveness { // // # Tracked lvalues // - // A tracked lvalue is a local variable/argument `x`. In + // A tracked lvalue is either a local variable/argument `x` or + // else it is a self-field `self.f` in a constructor. In // these cases, the link_node where the write occurs is linked - // to node id of `x`. The `write_lvalue()` routine generates - // the contents of this node. There are no subcomponents to - // consider. + // to node id of `x` or `self`, respectively. The + // `write_lvalue()` routine generates the contents of this + // node. There are no subcomponents to consider. // // # Non-tracked lvalues // @@ -1257,9 +1315,12 @@ impl Liveness { // just ignore such cases and treat them as reads. match expr.node { - expr_path(_) => succ, - expr_field(e, _, _) => self.propagate_through_expr(e, succ), - _ => self.propagate_through_expr(expr, succ) + expr_path(_) => succ, + expr_field(e, nm, _) => match self.as_self_field(e, nm) { + Some(_) => succ, + None => self.propagate_through_expr(e, succ) + }, + _ => self.propagate_through_expr(expr, succ) } } @@ -1269,6 +1330,14 @@ impl Liveness { acc: uint) -> LiveNode { match expr.node { expr_path(_) => self.access_path(expr, succ, acc), + expr_field(e, nm, _) => match self.as_self_field(e, nm) { + Some((ln, var)) => { + self.init_from_succ(ln, succ); + self.acc(ln, var, acc); + ln + } + None => succ + }, // We do not track other lvalues, so just propagate through // to their subcomponents. Also, it may happen that @@ -1281,6 +1350,26 @@ impl Liveness { fn access_path(expr: @expr, succ: LiveNode, acc: uint) -> LiveNode { let def = self.tcx.def_map.get(expr.id); match relevant_def(def) { + Some(RelevantSelf) => { + // Accessing `self` is like accessing every field of + // the current object. This allows something like + // `self = ...;` (it will be considered a write to + // every field, sensibly enough), though the borrowck + // pass will reject it later on. + // + // Also, note that, within a ctor at least, an + // expression like `self.f` is "shortcircuiting" + // before it reaches this point by the code for + // expr_field. + let ln = self.live_node(expr.id, expr.span); + if acc != 0u { + self.init_from_succ(ln, succ); + for self.ir.field_map.each_value |var| { + self.acc(ln, var, acc); + } + } + ln + } Some(RelevantVar(nid)) => { let ln = self.live_node(expr.id, expr.span); if acc != 0u { @@ -1294,6 +1383,29 @@ impl Liveness { } } + fn as_self_field(expr: @expr, + fld: ident) -> Option<(LiveNode,Variable)> { + // If we checking a constructor, then we treat self.f as a + // variable. we use the live_node id that will be assigned to + // the reference to self but the variable id for `f`. + match expr.node { + expr_path(_) => { + let def = self.tcx.def_map.get(expr.id); + match def { + def_self(_) => { + // Note: the field_map is empty unless we are in a ctor + return self.ir.field_map.find(fld).map(|var| { + let ln = self.live_node(expr.id, expr.span); + (ln, *var) + }); + } + _ => return None + } + } + _ => return None + } + } + fn propagate_through_loop(expr: @expr, cond: Option<@expr>, body: blk, @@ -1501,7 +1613,24 @@ enum ReadKind { } impl @Liveness { - fn check_ret(id: node_id, sp: span, _fk: visit::fn_kind, + fn check_fields(sp: span, entry_ln: LiveNode) { + for self.ir.field_map.each |nm, var| { + match self.live_on_entry(entry_ln, var) { + None => { /* ok */ } + Some(ExitNode) => { + self.tcx.sess.span_err( + sp, fmt!("field `self.%s` is never initialized", + self.tcx.sess.str_of(nm))); + } + Some(lnk) => { + self.report_illegal_read( + sp, lnk, var, PossiblyUninitializedField); + } + } + } + } + + fn check_ret(id: node_id, sp: span, fk: visit::fn_kind, entry_ln: LiveNode) { if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { // if no_ret_var is live, then we fall off the end of the @@ -1515,8 +1644,15 @@ impl @Liveness { self.tcx.sess.span_err( sp, ~"some control paths may return"); } else { - self.tcx.sess.span_err( - sp, ~"not all control paths return a value"); + match fk { + visit::fk_ctor(*) => { + // ctors are written as though they are unit. + } + _ => { + self.tcx.sess.span_err( + sp, ~"not all control paths return a value"); + } + } } } } @@ -1601,6 +1737,7 @@ impl @Liveness { let var = self.variable(nid, expr.span); self.warn_about_dead_assign(expr.span, ln, var); } + Some(RelevantSelf) => {} None => {} } } @@ -1659,6 +1796,13 @@ impl @Liveness { copy or move mode", self.tcx.sess.str_of(name))); return; } + Field(name) => { + self.tcx.sess.span_err( + move_span, + fmt!("illegal move from field `%s`", + self.tcx.sess.str_of(name))); + return; + } Self => { self.tcx.sess.span_err( move_span, diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index eb0bf8796f07..ff708b7f4efa 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -305,16 +305,16 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visitor: visit::vt) { let fn_cx = match fk { - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_dtor(*) => { - // Top-level functions are a root scope. - ctxt {parent: Some(id),.. cx} - } + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_ctor(*) | visit::fk_dtor(*) => { + // Top-level functions are a root scope. + ctxt {parent: Some(id),.. cx} + } - visit::fk_anon(*) | visit::fk_fn_block(*) => { - // Closures continue with the inherited scope. - cx - } + visit::fk_anon(*) | visit::fk_fn_block(*) => { + // Closures continue with the inherited scope. + cx + } }; debug!("visiting fn with body %d. cx.parent: %? \ @@ -641,7 +641,7 @@ fn determine_rp_in_ty(ty: @ast::ty, match ty.node { ast::ty_path(path, id) => { match cx.def_map.get(id) { - ast::def_ty(did) | ast::def_class(did) => { + ast::def_ty(did) | ast::def_class(did, _) => { if did.crate == ast::local_crate { if cx.opt_region_is_relevant(path.rp) { cx.add_dep(did.node); diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index b455cc257ef1..5f30346a28e8 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -757,7 +757,7 @@ struct Resolver { unused_import_lint_level: level, trait_info: HashMap>, - structs: HashMap, + structs: HashMap, // The number of imports that are currently unresolved. mut unresolved_imports: uint, @@ -1069,15 +1069,36 @@ impl Resolver { } // These items live in both the type and value namespaces. - item_class(*) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[TypeNS], sp); + item_class(struct_definition, _) => { + let new_parent = + match struct_definition.ctor { + None => { + let (name_bindings, new_parent) = + self.add_child(ident, parent, ~[TypeNS], sp); - (*name_bindings).define_type - (privacy, def_ty(local_def(item.id)), sp); + (*name_bindings).define_type + (privacy, def_ty(local_def(item.id)), sp); + new_parent + } + Some(ctor) => { + let (name_bindings, new_parent) = + self.add_child(ident, parent, ~[ValueNS, TypeNS], + sp); + + (*name_bindings).define_type + (privacy, def_ty(local_def(item.id)), sp); + + let purity = impure_fn; + let ctor_def = def_fn(local_def(ctor.node.id), + purity); + (*name_bindings).define_value(privacy, ctor_def, sp); + new_parent + } + }; // Record the def ID of this struct. - self.structs.insert(local_def(item.id), ()); + self.structs.insert(local_def(item.id), + struct_definition.ctor.is_some()); visit_item(item, new_parent, visitor); } @@ -1162,7 +1183,7 @@ impl Resolver { def_variant(item_id, local_def(variant.node.id)), variant.span); - self.structs.insert(local_def(variant.node.id), ()); + self.structs.insert(local_def(variant.node.id), false); } enum_variant_kind(enum_definition) => { (*child).define_type(privacy, @@ -1499,12 +1520,18 @@ impl Resolver { child_name_bindings.define_type(Public, def, dummy_sp()); } - def_class(def_id) => { + def_class(def_id, has_constructor) => { debug!("(building reduced graph for external \ - crate) building type %s", - final_ident); + crate) building type %s (value? %d)", + final_ident, + if has_constructor { 1 } else { 0 }); child_name_bindings.define_type(Public, def, dummy_sp()); - self.structs.insert(def_id, ()); + + if has_constructor { + child_name_bindings.define_value(Public, def, dummy_sp()); + } + + self.structs.insert(def_id, has_constructor); } def_self(*) | def_arg(*) | def_local(*) | def_prim_ty(*) | def_ty_param(*) | def_binding(*) | @@ -3279,6 +3306,7 @@ impl Resolver { struct_def.traits, struct_def.fields, struct_def.methods, + struct_def.ctor, struct_def.dtor, visitor); } @@ -3520,6 +3548,7 @@ impl Resolver { traits: ~[@trait_ref], fields: ~[@struct_field], methods: ~[@method], + optional_constructor: Option, optional_destructor: Option, visitor: ResolveVisitor) { @@ -3571,6 +3600,23 @@ impl Resolver { self.resolve_type(field.node.ty, visitor); } + // Resolve the constructor, if applicable. + match optional_constructor { + None => { + // Nothing to do. + } + Some(constructor) => { + self.resolve_function(NormalRibKind, + Some(@constructor.node.dec), + NoTypeParameters, + constructor.node.body, + HasSelfBinding(constructor.node. + self_id), + NoCaptureClause, + visitor); + } + } + // Resolve the destructor, if applicable. match optional_destructor { None => { @@ -4043,7 +4089,9 @@ impl Resolver { match self.resolve_path(path, TypeNS, false, visitor) { Some(def_ty(class_id)) if self.structs.contains_key(class_id) => { - let class_def = def_class(class_id); + let has_constructor = self.structs.get(class_id); + let class_def = def_class(class_id, + has_constructor); self.record_def(pattern.id, class_def); } Some(definition @ def_variant(_, variant_id)) @@ -4511,9 +4559,10 @@ impl Resolver { // let bar = Bar { ... } // no type parameters match self.resolve_path(path, TypeNS, false, visitor) { - Some(def_ty(class_id)) | Some(def_class(class_id)) + Some(def_ty(class_id)) | Some(def_class(class_id, _)) if self.structs.contains_key(class_id) => { - let class_def = def_class(class_id); + let has_constructor = self.structs.get(class_id); + let class_def = def_class(class_id, has_constructor); self.record_def(expr.id, class_def); } Some(definition @ def_variant(_, class_id)) diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index c605fe398734..95711f8da36a 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1596,14 +1596,18 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, // translation calls that don't have a return value (trans_crate, // trans_mod, trans_item, et cetera) and those that do // (trans_block, trans_expr, et cetera). - if body.node.expr.is_none() || ty::type_is_bot(block_ty) || - ty::type_is_nil(block_ty) - { + + if !ccx.class_ctors.contains_key(id) // hack -- + /* avoids the need for special cases to assign a type to + the constructor body (since it has no explicit return) */ + && + (body.node.expr.is_none() || + ty::type_is_bot(block_ty) || + ty::type_is_nil(block_ty)) { bcx = controlflow::trans_block(bcx, body, expr::Ignore); } else { bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr)); } - finish(bcx); cleanup_and_Br(bcx, bcx_top, fcx.llreturn); @@ -1694,6 +1698,60 @@ fn trans_enum_variant(ccx: @crate_ctxt, finish_fn(fcx, lltop); } +fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, + body: ast::blk, llctor_decl: ValueRef, + psubsts: param_substs, ctor_id: ast::node_id, + parent_id: ast::def_id, sp: span) { + // Add ctor to the ctor map + ccx.class_ctors.insert(ctor_id, parent_id); + + // Translate the ctor + + // Set up the type for the result of the ctor + // kludgy -- this wouldn't be necessary if the typechecker + // special-cased constructors, then we could just look up + // the ctor's return type. + let rslt_ty = ty::mk_class(ccx.tcx, parent_id, + dummy_substs(psubsts.tys)); + + // Make the fn context + let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, + Some(psubsts), Some(sp)); + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, decl.inputs); + let mut bcx_top = top_scope_block(fcx, body.info()); + let lltop = bcx_top.llbb; + let arg_tys = ty::ty_fn_args(node_id_type(bcx_top, ctor_id)); + bcx_top = copy_args_to_allocas(fcx, bcx_top, decl.inputs, + raw_llargs, arg_tys); + + // Create a temporary for `self` that we will return at the end + let selfdatum = datum::scratch_datum(bcx_top, rslt_ty, true); + + // Initialize dtor flag (if any) to 1 + if ty::ty_dtor(bcx_top.tcx(), parent_id).is_some() { + let flag = GEPi(bcx_top, selfdatum.val, [0, 1]); + Store(bcx_top, C_u8(1), flag); + } + + // initialize fields to zero + let mut bcx = bcx_top; + + // note we don't want to take *or* drop self. + fcx.llself = Some(ValSelfData {v: selfdatum.val, + t: rslt_ty, + is_owned: false}); + + // Translate the body of the ctor + bcx = controlflow::trans_block(bcx, body, expr::Ignore); + + // Generate the return expression + bcx = selfdatum.move_to(bcx, datum::INIT, fcx.llretptr); + + cleanup_and_leave(bcx, None, Some(fcx.llreturn)); + Unreachable(bcx); + finish_fn(fcx, lltop); +} + fn trans_class_dtor(ccx: @crate_ctxt, path: path, body: ast::blk, dtor_id: ast::node_id, psubsts: Option, @@ -1863,6 +1921,14 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, tps: ~[ast::ty_param], path: @ast_map::path, ident: ast::ident, id: ast::node_id) { if tps.len() == 0u { + let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps), + vtables: None, + bounds: @~[]}; + do option::iter(&struct_def.ctor) |ctor| { + trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body, + get_item_val(ccx, ctor.node.id), psubsts, + ctor.node.id, local_def(id), ctor.span); + } do option::iter(&struct_def.dtor) |dtor| { trans_class_dtor(ccx, *path, dtor.node.body, dtor.node.id, None, None, local_def(id)); @@ -2118,6 +2184,10 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { } } } + ast_map::node_ctor(nm, _, ctor, _, pt) => { + let my_path = vec::append(*pt, ~[path_name(nm)]); + register_fn(ccx, ctor.span, my_path, ctor.node.id) + } ast_map::node_dtor(_, dt, parent_id, pt) => { /* Don't just call register_fn, since we don't want to add @@ -2642,6 +2712,7 @@ fn trans_crate(sess: session::session, crate_map: crate_map, mut uses_gc: false, dbg_cx: dbg_cx, + class_ctors: HashMap(), mut do_not_commit_warning_issued: false}; diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index b87d690a1c34..68e957bfe709 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -170,6 +170,11 @@ type crate_ctxt = { // is not emitted by LLVM's GC pass when no functions use GC. mut uses_gc: bool, dbg_cx: Option, + // Mapping from class constructors to parent class -- + // used in base::trans_closure + // parent_class must be a def_id because ctors can be + // inlined, so the parent may be in a different crate + class_ctors: HashMap, mut do_not_commit_warning_issued: bool}; // Types used for llself. diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs index 068ec49d6c7e..6cd4b49fa3b3 100644 --- a/src/rustc/middle/trans/debuginfo.rs +++ b/src/rustc/middle/trans/debuginfo.rs @@ -732,6 +732,10 @@ fn create_function(fcx: fn_ctxt) -> @metadata { ast_map::node_method(method, _, _) => { (method.ident, method.decl.output, method.id) } + ast_map::node_ctor(nm, _, ctor, _, _) => { + // FIXME: output type may be wrong (#2194) + (nm, ctor.node.dec.output, ctor.node.id) + } ast_map::node_expr(expr) => { match expr.node { ast::expr_fn(_, decl, _, _) => { diff --git a/src/rustc/middle/trans/inline.rs b/src/rustc/middle/trans/inline.rs index ce9088d4b55c..76888471bf97 100644 --- a/src/rustc/middle/trans/inline.rs +++ b/src/rustc/middle/trans/inline.rs @@ -34,6 +34,10 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) trans_item(ccx, *item); local_def(item.id) } + csearch::found(ast::ii_ctor(ctor, _, _, _)) => { + ccx.external.insert(fn_id, Some(ctor.node.id)); + local_def(ctor.node.id) + } csearch::found(ast::ii_foreign(item)) => { ccx.external.insert(fn_id, Some(item.id)); local_def(item.id) diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 32a581454d3d..17eaf591c9f3 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -5,7 +5,7 @@ use syntax::ast_map::{path, path_mod, path_name}; use base::{trans_item, get_item_val, no_self, self_arg, trans_fn, impl_self, decl_internal_cdecl_fn, set_inline_hint_if_appr, set_inline_hint, - trans_enum_variant, trans_class_dtor, + trans_enum_variant, trans_class_ctor, trans_class_dtor, get_insn_ctxt}; use syntax::parse::token::special_idents; use type_of::type_of_fn_from_ty; @@ -71,6 +71,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, return {val: get_item_val(ccx, fn_id.node), must_cast: true}; } + ast_map::node_ctor(nm, _, ct, _, pt) => (pt, nm, ct.span), ast_map::node_dtor(_, dtor, _, pt) => (pt, special_idents::dtor, dtor.span), ast_map::node_trait_method(*) => { @@ -161,6 +162,16 @@ fn monomorphic_fn(ccx: @crate_ctxt, meth::trans_method(ccx, pt, mth, psubsts, None, d); d } + ast_map::node_ctor(_, tps, ctor, parent_id, _) => { + // ctors don't have attrs, at least not right now + let d = mk_lldecl(); + let tp_tys = ty::ty_params_to_tys(ccx.tcx, tps); + trans_class_ctor(ccx, pt, ctor.node.dec, ctor.node.body, d, + option::get_default(&psubsts, + {tys:tp_tys, vtables: None, bounds: @~[]}), + fn_id.node, parent_id, ctor.span); + d + } ast_map::node_dtor(_, dtor, _, pt) => { let parent_id = match ty::ty_to_def_id(ty::node_id_to_type(ccx.tcx, dtor.node.self_id)) { diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs index bfb8de76a6c5..3c4439c918fb 100644 --- a/src/rustc/middle/trans/reachable.rs +++ b/src/rustc/middle/trans/reachable.rs @@ -59,6 +59,10 @@ fn traverse_def_id(cx: ctx, did: def_id) { cx.rmap.insert(item.id, ()); } ast_map::node_variant(v, _, _) => { cx.rmap.insert(v.node.id, ()); } + // If it's a ctor, consider the parent reachable + ast_map::node_ctor(_, _, _, parent_id, _) => { + traverse_def_id(cx, parent_id); + } _ => () } } @@ -100,6 +104,13 @@ fn traverse_public_item(cx: ctx, item: @item) { } } item_class(struct_def, tps) => { + do option::iter(&struct_def.ctor) |ctor| { + cx.rmap.insert(ctor.node.id, ()); + if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs) + != attr::ia_none { + traverse_inline_body(cx, ctor.node.body); + } + } do option::iter(&struct_def.dtor) |dtor| { cx.rmap.insert(dtor.node.id, ()); if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs) diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 1f9ad20dd03e..ee247eb5db79 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -109,6 +109,9 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;} } } + ast_map::node_ctor(_, _, ctor, _, _) => { + handle_body(cx, ctor.node.body); + } ast_map::node_dtor(_, dtor, _, _) => { handle_body(cx, dtor.node.body); } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index ff916d55b6ff..bbc3a06fb675 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -3318,7 +3318,7 @@ fn note_and_explain_type_err(cx: ctxt, err: &type_err) { fn def_has_ty_params(def: ast::def) -> bool { match def { - ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_) + ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_, _) => true, _ => false } @@ -3492,6 +3492,9 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path { ast_map::path_name(variant.node.name)) } + ast_map::node_ctor(nm, _, _, _, path) => { + vec::append_one(*path, ast_map::path_name(nm)) + } ast_map::node_dtor(_, _, _, path) => { vec::append_one(*path, ast_map::path_name( syntax::parse::token::special_idents::literally_dtor)) diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index 389c1adb016b..14797fcdd6bb 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -323,7 +323,7 @@ fn ast_ty_to_ty( Some(d) => d }; match a_def { - ast::def_ty(did) | ast::def_class(did) => { + ast::def_ty(did) | ast::def_class(did, _) => { ast_path_to_ty(self, rscope, did, path, id).ty } ast::def_prim_ty(nty) => { diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 1d921497ccf4..7cc2c8b0ad76 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -451,6 +451,18 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, let tcx = ccx.tcx; let self_ty = ty::node_id_to_type(tcx, id); + do option::iter(&struct_def.ctor) |ctor| { + let class_t = {self_ty: self_ty, + self_id: ctor.node.self_id, + def_id: local_def(id), + explicit_self: {node: ast::sty_by_ref, + span: ast_util::dummy_sp()}}; + // typecheck the ctor + check_bare_fn(ccx, ctor.node.dec, + ctor.node.body, ctor.node.id, + Some(class_t)); + } + do option::iter(&struct_def.dtor) |dtor| { let class_t = {self_ty: self_ty, self_id: dtor.node.self_id, @@ -1913,7 +1925,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Resolve the path. let class_id; match tcx.def_map.find(id) { - Some(ast::def_class(type_def_id)) => { + Some(ast::def_class(type_def_id, _)) => { class_id = type_def_id; } _ => { @@ -2400,7 +2412,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> ast::def_fn(id, _) | ast::def_static_method(id, _) | ast::def_const(id) | ast::def_variant(_, id) | - ast::def_class(id) => { + ast::def_class(id, _) => { return ty::lookup_item_type(fcx.ccx.tcx, id); } ast::def_upvar(_, inner, _, _) => { diff --git a/src/rustc/middle/typeck/check/alt.rs b/src/rustc/middle/typeck/check/alt.rs index 24bcc2281fb9..0b2e9c8ab3dd 100644 --- a/src/rustc/middle/typeck/check/alt.rs +++ b/src/rustc/middle/typeck/check/alt.rs @@ -325,7 +325,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { // Check to ensure that the struct is the one specified. match tcx.def_map.get(pat.id) { - ast::def_class(supplied_def_id) + ast::def_class(supplied_def_id, _) if supplied_def_id == class_id => { // OK. } diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 472c8a30459d..18e29981af30 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -497,6 +497,30 @@ fn convert_struct(ccx: @crate_ctxt, tpt: ty::ty_param_bounds_and_ty, id: ast::node_id) { let tcx = ccx.tcx; + do option::iter(&struct_def.ctor) |ctor| { + // Write the ctor type + let t_args = ctor.node.dec.inputs.map( + |a| ty_of_arg(ccx, type_rscope(rp), *a, None) ); + let t_res = ty::mk_class( + tcx, local_def(id), + {self_r: rscope::bound_self_region(rp), + self_ty: None, + tps: ty::ty_params_to_tys(tcx, tps)}); + let proto = ty::proto_vstore(ty::vstore_slice(ty::re_static)); + let t_ctor = ty::mk_fn(tcx, FnTyBase { + meta: FnMeta {purity: ast::impure_fn, + proto: proto, + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: t_args, + output: t_res} + }); + write_ty_to_tcx(tcx, ctor.node.id, t_ctor); + tcx.tcache.insert(local_def(ctor.node.id), + {bounds: tpt.bounds, + region_param: rp, + ty: t_ctor}); + } do option::iter(&struct_def.dtor) |dtor| { // Write the dtor type diff --git a/src/test/compile-fail/issue-2590.rs b/src/test/compile-fail/issue-2590.rs index 0f4a4804c751..f4ccd901fb3a 100644 --- a/src/test/compile-fail/issue-2590.rs +++ b/src/test/compile-fail/issue-2590.rs @@ -10,7 +10,7 @@ trait parse { impl parser: parse { fn parse() -> ~[int] { - dvec::unwrap(move self.tokens) //~ ERROR moving out of immutable field + dvec::unwrap(move self.tokens) //~ ERROR illegal move from self } } diff --git a/src/test/compile-fail/regions-glb-free-free.rs b/src/test/compile-fail/regions-glb-free-free.rs index e4913f7056e8..223665381da1 100644 --- a/src/test/compile-fail/regions-glb-free-free.rs +++ b/src/test/compile-fail/regions-glb-free-free.rs @@ -19,7 +19,7 @@ mod argparse { fn set_desc(self, s: &str) -> Flag { Flag { //~ ERROR cannot infer an appropriate lifetime name: self.name, - desc: s, //~ ERROR cannot infer an appropriate lifetime + desc: s, max_count: self.max_count, value: self.value } From 639f568ec9aab94f3d46abdc9a2b74e6bec4705a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 09:02:56 -0700 Subject: [PATCH 026/292] Register snapshots --- src/snapshots.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/snapshots.txt b/src/snapshots.txt index e1469d99d2b7..e08be23e5e52 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,11 @@ +S 2012-10-07 d301dd3 + macos-i386 c9dfce9f231f22969b7e7995c1f39fcf86f81b2b + macos-x86_64 3b1f6fd43fe03d7af334eeb111bc384428c4cd3d + freebsd-x86_64 784ac161fee0351281e3edfefc81a0c1b5d068b5 + linux-i386 4d945d7e0de4e4544928ed5aa111d1508522c69 + linux-x86_64 9bea5436042dd4bb7e682d3a10d0d51c3590b531 + winnt-i386 62de5eea3eba70a2f4a2b4d42c72aa2fa75f999a + S 2012-10-05 937f8f4 macos-i386 8b5ddc78b3004e539c6fbe224e492e4a6a1bc867 macos-x86_64 03793e0136512c644edfb5f13cc5bb7d67fb24e5 From 1ac75d226957cf0ec6b596541f4fd688f49bc300 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 8 Oct 2012 10:41:02 -0700 Subject: [PATCH 027/292] allow interner cache to be shared across parsers (#3699) --- src/libsyntax/parse/token.rs | 47 ++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 19e79a4ae7a9..5e928d086b86 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -343,28 +343,33 @@ macro_rules! interner_key ( ) fn mk_ident_interner() -> @ident_interner { - /* the indices here must correspond to the numbers in special_idents */ - let init_vec = ~[@~"_", @~"anon", @~"drop", @~"", @~"unary", @~"!", - @~"[]", @~"unary-", @~"__extensions__", @~"self", - @~"item", @~"block", @~"stmt", @~"pat", @~"expr", - @~"ty", @~"ident", @~"path", @~"tt", @~"matchers", - @~"str", @~"TyVisitor", @~"arg", @~"descrim", - @~"__rust_abi", @~"__rust_stack_shim", @~"TyDesc", - @~"dtor", @~"main", @~"", @~"blk", @~"static", - @~"intrinsic", @~"__foreign_mod__"]; - - let rv = @ident_interner { - interner: interner::mk_prefill::<@~str>(init_vec) - }; - - /* having multiple interners will just confuse the serializer */ unsafe { - assert task::local_data::local_data_get(interner_key!()).is_none() - }; - unsafe { - task::local_data::local_data_set(interner_key!(), @rv) - }; - rv + match task::local_data::local_data_get(interner_key!()) { + Some(interner) => *interner, + None => { + // the indices here must correspond to the numbers in + // special_idents. + let init_vec = ~[ + @~"_", @~"anon", @~"drop", @~"", @~"unary", @~"!", + @~"[]", @~"unary-", @~"__extensions__", @~"self", + @~"item", @~"block", @~"stmt", @~"pat", @~"expr", + @~"ty", @~"ident", @~"path", @~"tt", @~"matchers", + @~"str", @~"TyVisitor", @~"arg", @~"descrim", + @~"__rust_abi", @~"__rust_stack_shim", @~"TyDesc", + @~"dtor", @~"main", @~"", @~"blk", @~"static", + @~"intrinsic", @~"__foreign_mod__" + ]; + + let rv = @ident_interner { + interner: interner::mk_prefill(init_vec) + }; + + task::local_data::local_data_set(interner_key!(), @rv); + + rv + } + } + } } /* for when we don't care about the contents; doesn't interact with TLD or From 04a3d9514ce5a3d0db0c96f619a6499aa4234fa9 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 10:53:21 -0700 Subject: [PATCH 028/292] Fix typo in linux-i386 snapshot hash --- src/snapshots.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/snapshots.txt b/src/snapshots.txt index e08be23e5e52..9ba0c82465f3 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,10 +1,10 @@ S 2012-10-07 d301dd3 - macos-i386 c9dfce9f231f22969b7e7995c1f39fcf86f81b2b - macos-x86_64 3b1f6fd43fe03d7af334eeb111bc384428c4cd3d + macos-i386 c9dfce9f231f22969b7e7995c1f39fcf86f81b2b + macos-x86_64 3b1f6fd43fe03d7af334eeb111bc384428c4cd3d freebsd-x86_64 784ac161fee0351281e3edfefc81a0c1b5d068b5 - linux-i386 4d945d7e0de4e4544928ed5aa111d1508522c69 - linux-x86_64 9bea5436042dd4bb7e682d3a10d0d51c3590b531 - winnt-i386 62de5eea3eba70a2f4a2b4d42c72aa2fa75f999a + linux-i386 4d945d7e0de4e4544928ed5aa111d1508522c697 + linux-x86_64 9bea5436042dd4bb7e682d3a10d0d51c3590b531 + winnt-i386 62de5eea3eba70a2f4a2b4d42c72aa2fa75f999a S 2012-10-05 937f8f4 macos-i386 8b5ddc78b3004e539c6fbe224e492e4a6a1bc867 From 73ec5f09b072734f68b7f784f2343568bd4c3bd9 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 11:11:09 -0700 Subject: [PATCH 029/292] Remove extra spaces from snapshots.txt --- src/etc/snapshot.py | 3 ++- src/snapshots.txt | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/etc/snapshot.py b/src/etc/snapshot.py index 780ba4282094..dbf13454203d 100644 --- a/src/etc/snapshot.py +++ b/src/etc/snapshot.py @@ -68,7 +68,8 @@ def parse_line(n, line): match = re.match(r"([ST]) (\d{4}-\d{2}-\d{2}) ([a-fA-F\d]+)\s*$", line); if (not match): - raise Exception("%s:%d:E syntax error" % (snapshotfile, n)) + raise Exception("%s:%d:%s:E syntax error: line = %s" + % (snapshotfile, n, hash, line)) return {"type": "snapshot", "date": match.group(2), "rev": match.group(3)} diff --git a/src/snapshots.txt b/src/snapshots.txt index 9ba0c82465f3..6037a2d49583 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,10 +1,10 @@ S 2012-10-07 d301dd3 - macos-i386 c9dfce9f231f22969b7e7995c1f39fcf86f81b2b - macos-x86_64 3b1f6fd43fe03d7af334eeb111bc384428c4cd3d + macos-i386 c9dfce9f231f22969b7e7995c1f39fcf86f81b2b + macos-x86_64 3b1f6fd43fe03d7af334eeb111bc384428c4cd3d freebsd-x86_64 784ac161fee0351281e3edfefc81a0c1b5d068b5 - linux-i386 4d945d7e0de4e4544928ed5aa111d1508522c697 - linux-x86_64 9bea5436042dd4bb7e682d3a10d0d51c3590b531 - winnt-i386 62de5eea3eba70a2f4a2b4d42c72aa2fa75f999a + linux-i386 4d945d7e0de4e4544928ed5aa111d1508522c697 + linux-x86_64 9bea5436042dd4bb7e682d3a10d0d51c3590b531 + winnt-i386 62de5eea3eba70a2f4a2b4d42c72aa2fa75f999a S 2012-10-05 937f8f4 macos-i386 8b5ddc78b3004e539c6fbe224e492e4a6a1bc867 From a33535e441dc5461fec0489069a1491367ad1c91 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 11:54:09 -0700 Subject: [PATCH 030/292] Revert "Remove old auto_serialize2 code (needs snapshot)" This reverts commit 0bd6da8a8c93143325cb45e8a074ccf7121ca168. --- src/libsyntax/ast.rs | 170 +++++ src/libsyntax/ast_util.rs | 2 + src/libsyntax/ext/auto_serialize2.rs | 991 +++++++++++++++++++++++++++ src/libsyntax/ext/base.rs | 61 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/parse/token.rs | 6 + src/libsyntax/syntax.rc | 3 + src/rustc/middle/freevars.rs | 2 + src/rustc/middle/ty.rs | 16 + src/rustc/middle/typeck.rs | 4 + 10 files changed, 1255 insertions(+), 2 deletions(-) create mode 100644 src/libsyntax/ext/auto_serialize2.rs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a27336097d0c..f3e118461e66 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -20,6 +20,8 @@ impl span: Deserializable { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type spanned = {node: T, span: span}; @@ -76,6 +78,8 @@ type fn_ident = Option; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type path = {span: span, global: bool, idents: ~[ident], @@ -88,6 +92,8 @@ type node_id = int; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type def_id = {crate: crate_num, node: node_id}; impl def_id : cmp::Eq { @@ -102,6 +108,8 @@ const crate_node_id: node_id = 0; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum ty_param_bound { bound_copy, bound_send, @@ -112,10 +120,14 @@ enum ty_param_bound { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum def { def_fn(def_id, purity), def_static_method(def_id, purity), @@ -296,6 +308,8 @@ type meta_item = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum meta_item_ { meta_word(~str), meta_list(~str, ~[@meta_item]), @@ -306,6 +320,8 @@ type blk = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type blk_ = {view_items: ~[@view_item], stmts: ~[@stmt], expr: Option<@expr>, @@ -314,14 +330,20 @@ type blk_ = {view_items: ~[@view_item], #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type pat = {id: node_id, node: pat_, span: span}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type field_pat = {ident: ident, pat: @pat}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum binding_mode { bind_by_value, bind_by_move, @@ -379,6 +401,8 @@ impl binding_mode : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -403,6 +427,8 @@ enum pat_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum mutability { m_mutbl, m_imm, m_const, } impl mutability : to_bytes::IterBytes { @@ -420,6 +446,8 @@ impl mutability : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum proto { proto_bare, // foreign fn proto_uniq, // fn~ @@ -436,6 +464,8 @@ impl proto : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -446,6 +476,8 @@ enum vstore { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum expr_vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) expr_vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -463,6 +495,8 @@ pure fn is_blockish(p: ast::proto) -> bool { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum binop { add, subtract, @@ -493,6 +527,8 @@ impl binop : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum unop { box(mutability), uniq(mutability), @@ -545,6 +581,8 @@ impl unop : cmp::Eq { // using ty::resolved_T(...). #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum inferable { expl(T), infer(node_id) @@ -585,6 +623,8 @@ impl inferable : cmp::Eq { // "resolved" mode: the real modes. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum rmode { by_ref, by_val, by_move, by_copy } impl rmode : to_bytes::IterBytes { @@ -608,6 +648,8 @@ type stmt = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum stmt_ { stmt_decl(@decl, node_id), @@ -620,6 +662,8 @@ enum stmt_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum init_op { init_assign, init_move, } impl init_op : cmp::Eq { @@ -644,12 +688,16 @@ impl init_op : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type initializer = {op: init_op, expr: @expr}; // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type local_ = {is_mutbl: bool, ty: @ty, pat: @pat, init: Option, id: node_id}; @@ -659,20 +707,28 @@ type decl = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum decl_ { decl_local(~[@local]), decl_item(@item), } #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type field_ = {mutbl: mutability, ident: ident, expr: @expr}; type field = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum blk_check_mode { default_blk, unsafe_blk, } impl blk_check_mode : cmp::Eq { @@ -689,20 +745,28 @@ impl blk_check_mode : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type expr = {id: node_id, callee_id: node_id, node: expr_, span: span}; // Extra node ID is only used for index, assign_op, unary, binary #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum log_level { error, debug, other } // 0 = error, 1 = debug, 2 = other #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum alt_mode { alt_check, alt_exhaustive, } #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum expr_ { expr_vstore(@expr, expr_vstore), expr_vec(~[@expr], mutability), @@ -760,6 +824,8 @@ enum expr_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type capture_item_ = { id: int, is_move: bool, @@ -789,6 +855,8 @@ type capture_clause = @~[capture_item]; // #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] #[doc="For macro invocations; parsing is delegated to the macro"] enum token_tree { tt_tok(span, token::token), @@ -854,6 +922,8 @@ type matcher = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum matcher_ { // match one token match_tok(token::token), @@ -870,12 +940,16 @@ type mac_arg = Option<@expr>; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type mac_body_ = {span: span}; type mac_body = Option; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum mac_ { mac_invoc(@path, mac_arg, mac_body), // old macro-invocation mac_invoc_tt(@path,~[token_tree]), // new macro-invocation @@ -890,6 +964,8 @@ type lit = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum lit_ { lit_str(@~str), lit_int(i64, int_ty), @@ -932,22 +1008,30 @@ impl ast::lit_: cmp::Eq { // type structure in middle/ty.rs as well. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type mt = {ty: @ty, mutbl: mutability}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_field_ = {ident: ident, mt: mt}; type ty_field = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_method = {ident: ident, attrs: ~[attribute], purity: purity, decl: fn_decl, tps: ~[ty_param], self_ty: self_ty, id: node_id, span: span}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] // A trait method is either required (meaning it doesn't have an // implementation, just a signature) or provided (meaning it has a default // implementation). @@ -958,6 +1042,8 @@ enum trait_method { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } impl int_ty : to_bytes::IterBytes { @@ -988,6 +1074,8 @@ impl int_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } impl uint_ty : to_bytes::IterBytes { @@ -1016,6 +1104,8 @@ impl uint_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum float_ty { ty_f, ty_f32, ty_f64, } impl float_ty : to_bytes::IterBytes { @@ -1035,11 +1125,15 @@ impl float_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type ty = {id: node_id, node: ty_, span: span}; // Not represented directly in the AST, referred to by name through a ty_path. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum prim_ty { ty_int(int_ty), ty_uint(uint_ty), @@ -1088,10 +1182,14 @@ impl prim_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type region = {id: node_id, node: region_}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum region_ { re_anon, re_static, @@ -1101,6 +1199,8 @@ enum region_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -1141,10 +1241,14 @@ impl ty : to_bytes::IterBytes { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type fn_decl = {inputs: ~[arg], output: @ty, @@ -1152,6 +1256,8 @@ type fn_decl = #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum purity { pure_fn, // declared with "pure fn" unsafe_fn, // declared with "unsafe fn" @@ -1174,6 +1280,8 @@ impl purity : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum ret_style { noreturn, // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) @@ -1200,6 +1308,8 @@ impl ret_style : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum self_ty_ { sty_static, // no self: static method sty_by_ref, // old by-reference self: `` @@ -1257,6 +1367,8 @@ type self_ty = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type method = {ident: ident, attrs: ~[attribute], tps: ~[ty_param], self_ty: self_ty, purity: purity, decl: fn_decl, body: blk, @@ -1265,10 +1377,14 @@ type method = {ident: ident, attrs: ~[attribute], #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type _mod = {view_items: ~[@view_item], items: ~[@item]}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_abi { foreign_abi_rust_intrinsic, foreign_abi_cdecl, @@ -1278,6 +1394,8 @@ enum foreign_abi { // Foreign mods can be named or anonymous #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_mod_sort { named, anonymous } impl foreign_mod_sort : cmp::Eq { @@ -1303,6 +1421,8 @@ impl foreign_abi : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type foreign_mod = {sort: foreign_mod_sort, view_items: ~[@view_item], @@ -1310,10 +1430,14 @@ type foreign_mod = #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type variant_arg = {ty: @ty, id: node_id}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum variant_kind { tuple_variant_kind(~[variant_arg]), struct_variant_kind(@struct_def), @@ -1322,14 +1446,20 @@ enum variant_kind { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type enum_def_ = { variants: ~[variant], common: Option<@struct_def> }; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum enum_def = enum_def_; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, id: node_id, disr_expr: Option<@expr>, vis: visibility}; @@ -1337,12 +1467,16 @@ type variant = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type path_list_ident_ = {name: ident, id: node_id}; type path_list_ident = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum namespace { module_ns, type_value_ns } impl namespace : cmp::Eq { @@ -1356,6 +1490,8 @@ type view_path = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum view_path_ { // quux = foo::bar::baz @@ -1374,11 +1510,15 @@ enum view_path_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type view_item = {node: view_item_, attrs: ~[attribute], vis: visibility, span: span}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum view_item_ { view_item_use(ident, ~[@meta_item], node_id), view_item_import(~[@view_path]), @@ -1393,6 +1533,8 @@ type attribute = spanned; // distinguished for pretty-printing. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum attr_style { attr_outer, attr_inner, } impl attr_style : cmp::Eq { @@ -1405,6 +1547,8 @@ impl attr_style : cmp::Eq { // doc-comments are promoted to attributes that have is_sugared_doc = true #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; /* @@ -1418,10 +1562,14 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; */ #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum visibility { public, private, inherited } impl visibility : cmp::Eq { @@ -1440,6 +1588,8 @@ impl visibility : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type struct_field_ = { kind: struct_field_kind, id: node_id, @@ -1450,6 +1600,8 @@ type struct_field = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum struct_field_kind { named_field(ident, class_mutability, visibility), unnamed_field // element of a tuple-like struct @@ -1457,6 +1609,8 @@ enum struct_field_kind { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type struct_def = { traits: ~[@trait_ref], /* traits this struct implements */ fields: ~[@struct_field], /* fields */ @@ -1474,12 +1628,16 @@ type struct_def = { */ #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type item = {ident: ident, attrs: ~[attribute], id: node_id, node: item_, vis: visibility, span: span}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum item_ { item_const(@ty, @expr), item_fn(fn_decl, purity, ~[ty_param], blk), @@ -1498,6 +1656,8 @@ enum item_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum class_mutability { class_mutable, class_immutable } impl class_mutability : to_bytes::IterBytes { @@ -1522,6 +1682,8 @@ type class_ctor = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type class_ctor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, @@ -1532,6 +1694,8 @@ type class_dtor = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type class_dtor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, @@ -1539,6 +1703,8 @@ type class_dtor_ = {id: node_id, #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type foreign_item = {ident: ident, attrs: ~[attribute], @@ -1549,6 +1715,8 @@ type foreign_item = #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_item_ { foreign_item_fn(fn_decl, purity, ~[ty_param]), foreign_item_const(@ty) @@ -1559,6 +1727,8 @@ enum foreign_item_ { // that we trans. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index ab24d7a53160..897a51f710c6 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -408,6 +408,8 @@ fn dtor_dec() -> fn_decl { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type id_range = {min: node_id, max: node_id}; fn empty(range: id_range) -> bool { diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs new file mode 100644 index 000000000000..b3102f8b4f72 --- /dev/null +++ b/src/libsyntax/ext/auto_serialize2.rs @@ -0,0 +1,991 @@ +/* + +The compiler code necessary to implement the #[auto_serialize2] and +#[auto_deserialize2] extension. The idea here is that type-defining items may +be tagged with #[auto_serialize2] and #[auto_deserialize2], which will cause +us to generate a little companion module with the same name as the item. + +For example, a type like: + + #[auto_serialize2] + #[auto_deserialize2] + struct Node {id: uint} + +would generate two implementations like: + + impl Node: Serializable { + fn serialize(s: &S) { + do s.emit_struct("Node") { + s.emit_field("id", 0, || s.emit_uint(self)) + } + } + } + + impl node_id: Deserializable { + static fn deserialize(d: &D) -> Node { + do d.read_struct("Node") { + Node { + id: d.read_field(~"x", 0, || deserialize(d)) + } + } + } + } + +Other interesting scenarios are whe the item has type parameters or +references other non-built-in types. A type definition like: + + #[auto_serialize2] + #[auto_deserialize2] + type spanned = {node: T, span: span}; + +would yield functions like: + + impl spanned: Serializable { + fn serialize(s: &S) { + do s.emit_rec { + s.emit_field("node", 0, || self.node.serialize(s)); + s.emit_field("span", 1, || self.span.serialize(s)); + } + } + } + + impl spanned: Deserializable { + static fn deserialize(d: &D) -> spanned { + do d.read_rec { + { + node: d.read_field(~"node", 0, || deserialize(d)), + span: d.read_field(~"span", 1, || deserialize(d)), + } + } + } + } + +FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the +standard library. + +Misc notes: +----------- + +I use move mode arguments for ast nodes that will get inserted as is +into the tree. This is intended to prevent us from inserting the same +node twice. + +*/ + +use base::*; +use codemap::span; +use std::map; +use std::map::HashMap; + +export expand_auto_serialize; +export expand_auto_deserialize; + +// Transitional reexports so qquote can find the paths it is looking for +mod syntax { + pub use ext; + pub use parse; +} + +fn expand_auto_serialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_serialize2(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_serialize2" + } + + fn filter_attrs(item: @ast::item) -> @ast::item { + @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize2(a)), + .. *item} + } + + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_serialize2) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let ser_impl = mk_rec_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let ser_impl = mk_struct_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + ast::item_enum(enum_def, tps) => { + let ser_impl = mk_enum_ser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_serialize2] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] + } + } +} + +fn expand_auto_deserialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_deserialize2(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_deserialize2" + } + + fn filter_attrs(item: @ast::item) -> @ast::item { + @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize2(a)), + .. *item} + } + + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_deserialize2) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let deser_impl = mk_rec_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let deser_impl = mk_struct_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_enum(enum_def, tps) => { + let deser_impl = mk_enum_deser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_deserialize2] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] + } + } +} + +fn mk_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + path: @ast::path, + tps: ~[ast::ty_param], + f: fn(@ast::ty) -> @ast::method +) -> @ast::item { + // All the type parameters need to bound to the trait. + let trait_tps = do tps.map |tp| { + let t_bound = ast::bound_trait(@{ + id: cx.next_id(), + node: ast::ty_path(path, cx.next_id()), + span: span, + }); + + { + ident: tp.ident, + id: cx.next_id(), + bounds: @vec::append(~[t_bound], *tp.bounds) + } + }; + + let opt_trait = Some(@{ + path: path, + ref_id: cx.next_id(), + impl_id: cx.next_id(), + }); + + let ty = cx.ty_path( + span, + ~[ident], + tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) + ); + + @{ + // This is a new-style impl declaration. + // XXX: clownshoes + ident: ast::token::special_idents::clownshoes_extensions, + attrs: ~[], + id: cx.next_id(), + node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), + vis: ast::public, + span: span, + } +} + +fn mk_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization2::Serializable trait. + let path = cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"Serializable"), + ] + ); + + mk_impl( + cx, + span, + ident, + path, + tps, + |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) + ) +} + +fn mk_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization2::Deserializable trait. + let path = cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"Deserializable"), + ] + ); + + mk_impl( + cx, + span, + ident, + path, + tps, + |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) + ) +} + +fn mk_ser_method( + cx: ext_ctxt, + span: span, + ser_body: ast::blk +) -> @ast::method { + let ser_bound = cx.ty_path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"Serializer"), + ], + ~[] + ); + + let ser_tps = ~[{ + ident: cx.ident_of(~"__S"), + id: cx.next_id(), + bounds: @~[ast::bound_trait(ser_bound)], + }]; + + let ty_s = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), + mutbl: ast::m_imm + } + ), + span: span, + }; + + let ser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_s, + ident: cx.ident_of(~"__s"), + id: cx.next_id(), + }]; + + let ser_output = @{ + id: cx.next_id(), + node: ast::ty_nil, + span: span, + }; + + let ser_decl = { + inputs: ser_inputs, + output: ser_output, + cf: ast::return_val, + }; + + @{ + ident: cx.ident_of(~"serialize"), + attrs: ~[], + tps: ser_tps, + self_ty: { node: ast::sty_region(ast::m_imm), span: span }, + purity: ast::impure_fn, + decl: ser_decl, + body: ser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, + } +} + +fn mk_deser_method( + cx: ext_ctxt, + span: span, + ty: @ast::ty, + deser_body: ast::blk +) -> @ast::method { + let deser_bound = cx.ty_path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"Deserializer"), + ], + ~[] + ); + + let deser_tps = ~[{ + ident: cx.ident_of(~"__D"), + id: cx.next_id(), + bounds: @~[ast::bound_trait(deser_bound)], + }]; + + let ty_d = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), + mutbl: ast::m_imm + } + ), + span: span, + }; + + let deser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_d, + ident: cx.ident_of(~"__d"), + id: cx.next_id(), + }]; + + let deser_decl = { + inputs: deser_inputs, + output: ty, + cf: ast::return_val, + }; + + @{ + ident: cx.ident_of(~"deserialize"), + attrs: ~[], + tps: deser_tps, + self_ty: { node: ast::sty_static, span: span }, + purity: ast::impure_fn, + decl: deser_decl, + body: deser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, + } +} + +fn mk_rec_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `__s.emit_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_rec") + ), + ~[cx.lambda_stmts(span, fields)] + ); + + mk_ser_impl(cx, span, ident, tps, body) +} + +fn mk_rec_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `read_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_rec") + ), + ~[ + cx.lambda_expr( + cx.expr( + span, + ast::expr_rec(fields, None) + ) + ) + ] + ); + + mk_deser_impl(cx, span, ident, tps, body) +} + +fn mk_struct_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); + + // ast for `__s.emit_struct($(name), || $(fields))` + let ser_body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_stmts(span, fields), + ] + ); + + mk_ser_impl(cx, span, ident, tps, ser_body) +} + +fn mk_struct_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); + + // ast for `read_struct($(name), || $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_expr( + cx.expr( + span, + ast::expr_struct( + cx.path(span, ~[ident]), + fields, + None + ) + ) + ), + ] + ); + + mk_deser_impl(cx, span, ident, tps, body) +} + +// Records and structs don't have the same fields types, but they share enough +// that if we extract the right subfields out we can share the serialization +// generator code. +type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; + +fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { + do fields.map |field| { + { + span: field.span, + ident: field.node.ident, + mutbl: field.node.mt.mutbl, + } + } +} + +fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { + do fields.map |field| { + let (ident, mutbl) = match field.node.kind { + ast::named_field(ident, mutbl, _) => (ident, mutbl), + _ => fail ~"[auto_serialize2] does not support \ + unnamed fields", + }; + + { + span: field.span, + ident: ident, + mutbl: match mutbl { + ast::class_mutable => ast::m_mutbl, + ast::class_immutable => ast::m_imm, + }, + } + } +} + +fn mk_ser_fields( + cx: ext_ctxt, + span: span, + fields: ~[field] +) -> ~[@ast::stmt] { + do fields.mapi |idx, field| { + // ast for `|| self.$(name).serialize(__s)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"self"), + field.ident + ), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` + cx.stmt( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ) + ) + } +} + +fn mk_deser_fields( + cx: ext_ctxt, + span: span, + fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] +) -> ~[ast::field] { + do fields.mapi |idx, field| { + // ast for `|| std::serialization2::deserialize(__d)` + let expr_lambda = cx.lambda( + cx.expr_blk( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ) + ); + + // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` + let expr: @ast::expr = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ); + + { + node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, + span: span, + } + } +} + +fn mk_enum_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_ser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_ser_impl(cx, span, ident, tps, body) +} + +fn mk_enum_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_deser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_deser_impl(cx, span, ident, tps, body) +} + +fn ser_variant( + cx: ext_ctxt, + span: span, + v_name: ast::ident, + v_idx: uint, + args: ~[ast::variant_arg] +) -> ast::arm { + // Name the variant arguments. + let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); + + // Bind the names to the variant argument type. + let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); + + let pat_node = if pats.is_empty() { + ast::pat_ident( + ast::bind_by_implicit_ref, + cx.path(span, ~[v_name]), + None + ) + } else { + ast::pat_enum( + cx.path(span, ~[v_name]), + Some(pats) + ) + }; + + let pat = @{ + id: cx.next_id(), + node: pat_node, + span: span, + }; + + let stmts = do args.mapi |a_idx, _arg| { + // ast for `__s.emit_enum_variant_arg` + let expr_emit = cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant_arg") + ); + + // ast for `|| $(v).serialize(__s)` + let expr_serialize = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_path(span, ~[names[a_idx]]), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` + cx.stmt( + cx.expr_call( + span, + expr_emit, + ~[cx.lit_uint(span, a_idx), expr_serialize] + ) + ) + }; + + // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant") + ), + ~[ + cx.lit_str(span, @cx.str_of(v_name)), + cx.lit_uint(span, v_idx), + cx.lit_uint(span, stmts.len()), + cx.lambda_stmts(span, stmts), + ] + ); + + { pats: ~[pat], guard: None, body: cx.expr_blk(body) } +} + +fn mk_enum_ser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let arms = do variants.mapi |v_idx, variant| { + match variant.node.kind { + ast::tuple_variant_kind(args) => + ser_variant(cx, span, variant.node.name, v_idx, args), + ast::struct_variant_kind(*) => + fail ~"struct variants unimplemented", + ast::enum_variant_kind(*) => + fail ~"enum variants unimplemented", + } + }; + + // ast for `match *self { $(arms) }` + let match_expr = cx.expr( + span, + ast::expr_match( + cx.expr( + span, + ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) + ), + arms + ) + ); + + // ast for `__s.emit_enum($(name), || $(match_expr))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + cx.lambda_expr(match_expr), + ] + ) +} + +fn mk_enum_deser_variant_nary( + cx: ext_ctxt, + span: span, + name: ast::ident, + args: ~[ast::variant_arg] +) -> @ast::expr { + let args = do args.mapi |idx, _arg| { + // ast for `|| std::serialization2::deserialize(__d)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ); + + // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant_arg") + ), + ~[cx.lit_uint(span, idx), expr_lambda] + ) + }; + + // ast for `$(name)($(args))` + cx.expr_call(span, cx.expr_path(span, ~[name]), args) +} + +fn mk_enum_deser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let mut arms = do variants.mapi |v_idx, variant| { + let body = match variant.node.kind { + ast::tuple_variant_kind(args) => { + if args.is_empty() { + // for a nullary variant v, do "v" + cx.expr_path(span, ~[variant.node.name]) + } else { + // for an n-ary variant v, do "v(a_1, ..., a_n)" + mk_enum_deser_variant_nary( + cx, + span, + variant.node.name, + args + ) + } + }, + ast::struct_variant_kind(*) => + fail ~"struct variants unimplemented", + ast::enum_variant_kind(*) => + fail ~"enum variants unimplemented", + }; + + let pat = @{ + id: cx.next_id(), + node: ast::pat_lit(cx.lit_uint(span, v_idx)), + span: span, + }; + + { + pats: ~[pat], + guard: None, + body: cx.expr_blk(body), + } + }; + + let impossible_case = { + pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], + guard: None, + + // FIXME(#3198): proper error message + body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), + }; + + arms.push(impossible_case); + + // ast for `|i| { match i { $(arms) } }` + let expr_lambda = cx.expr( + span, + ast::expr_fn_block( + { + inputs: ~[{ + mode: ast::infer(cx.next_id()), + ty: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span + }, + ident: cx.ident_of(~"i"), + id: cx.next_id(), + }], + output: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span, + }, + cf: ast::return_val, + }, + cx.expr_blk( + cx.expr( + span, + ast::expr_match(cx.expr_var(span, ~"i"), arms) + ) + ), + @~[] + ) + ); + + // ast for `__d.read_enum_variant($(expr_lambda))` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant") + ), + ~[expr_lambda] + ) + ); + + // ast for `__d.read_enum($(e_name), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + expr_lambda + ] + ) +} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index c106042b9a3d..ab56b6bb322e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -54,7 +54,7 @@ enum syntax_extension { // macro_defining() is obsolete, remove when #old_macros go away. macro_defining(macro_definer), - // #[auto_serialize] and such. will probably survive death of #old_macros + // #[auto_serialize2] and such. will probably survive death of #old_macros item_decorator(item_decorator), // Token-tree expanders @@ -64,6 +64,65 @@ enum syntax_extension { // A temporary hard-coded map of methods for expanding syntax extension // AST nodes into full ASTs +#[cfg(stage0)] +fn syntax_expander_table() -> HashMap<~str, syntax_extension> { + fn builtin(f: syntax_expander_) -> syntax_extension + {normal({expander: f, span: None})} + fn builtin_expr_tt(f: syntax_expander_tt_) -> syntax_extension { + expr_tt({expander: f, span: None}) + } + fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension { + item_tt({expander: f, span: None}) + } + let syntax_expanders = HashMap(); + syntax_expanders.insert(~"macro", + macro_defining(ext::simplext::add_new_extension)); + syntax_expanders.insert(~"macro_rules", + builtin_item_tt( + ext::tt::macro_rules::add_new_extension)); + syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); + syntax_expanders.insert( + ~"auto_serialize2", + item_decorator(ext::auto_serialize2::expand_auto_serialize)); + syntax_expanders.insert( + ~"auto_deserialize2", + item_decorator(ext::auto_serialize2::expand_auto_deserialize)); + syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext)); + syntax_expanders.insert(~"concat_idents", + builtin(ext::concat_idents::expand_syntax_ext)); + syntax_expanders.insert(~"ident_to_str", + builtin(ext::ident_to_str::expand_syntax_ext)); + syntax_expanders.insert(~"log_syntax", + builtin_expr_tt( + ext::log_syntax::expand_syntax_ext)); + syntax_expanders.insert(~"ast", + builtin(ext::qquote::expand_ast)); + syntax_expanders.insert(~"line", + builtin(ext::source_util::expand_line)); + syntax_expanders.insert(~"col", + builtin(ext::source_util::expand_col)); + syntax_expanders.insert(~"file", + builtin(ext::source_util::expand_file)); + syntax_expanders.insert(~"stringify", + builtin(ext::source_util::expand_stringify)); + syntax_expanders.insert(~"include", + builtin(ext::source_util::expand_include)); + syntax_expanders.insert(~"include_str", + builtin(ext::source_util::expand_include_str)); + syntax_expanders.insert(~"include_bin", + builtin(ext::source_util::expand_include_bin)); + syntax_expanders.insert(~"module_path", + builtin(ext::source_util::expand_mod)); + syntax_expanders.insert(~"proto", + builtin_item_tt(ext::pipes::expand_proto)); + syntax_expanders.insert( + ~"trace_macros", + builtin_expr_tt(ext::trace_macros::expand_trace_macros)); + return syntax_expanders; +} + +#[cfg(stage1)] +#[cfg(stage2)] fn syntax_expander_table() -> HashMap<~str, syntax_extension> { fn builtin(f: syntax_expander_) -> syntax_extension {normal({expander: f, span: None})} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 22e2cfcde6b5..2d0b2f4c80ab 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -124,7 +124,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, } // This is a secondary mechanism for invoking syntax extensions on items: -// "decorator" attributes, such as #[auto_serialize]. These are invoked by an +// "decorator" attributes, such as #[auto_serialize2]. These are invoked by an // attribute prefixing an item, and are interpreted by feeding the item // through the named attribute _as a syntax extension_ and splicing in the // resulting item vec into place in favour of the decorator. Note that diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index dce4dc3bbc7b..b63260997f75 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -4,6 +4,8 @@ use std::map::HashMap; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum binop { PLUS, MINUS, @@ -19,6 +21,8 @@ enum binop { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum token { /* Expression-operator symbols. */ EQ, @@ -77,6 +81,8 @@ enum token { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] /// For interpolation during macro expansion. enum nonterminal { nt_item(@ast::item), diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 93ed5bd471bc..4c29fc5512a7 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -130,6 +130,9 @@ mod ext { mod log_syntax; #[legacy_exports] mod auto_serialize; + #[cfg(stage0)] + #[legacy_exports] + mod auto_serialize2; #[legacy_exports] mod source_util; diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index 1b42c9bb4b67..28400b5455d5 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -18,6 +18,8 @@ export has_freevars; // (The def_upvar will already have been stripped). #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type freevar_entry = { def: ast::def, //< The variable being accessed free. span: span //< First span where it is accessed (there can be multiple) diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index ca41be6f9d0a..85f03e1f0b33 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -213,6 +213,8 @@ type mt = {ty: t, mutbl: ast::mutability}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum vstore { vstore_fixed(uint), vstore_uniq, @@ -273,6 +275,8 @@ type opt_region_variance = Option; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum region_variance { rv_covariant, rv_invariant, rv_contravariant } impl region_variance : cmp::Eq { @@ -291,6 +295,8 @@ impl region_variance : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type AutoAdjustment = { autoderefs: uint, autoref: Option @@ -298,6 +304,8 @@ type AutoAdjustment = { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type AutoRef = { kind: AutoRefKind, region: region, @@ -306,6 +314,8 @@ type AutoRef = { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum AutoRefKind { /// Convert from @[]/~[] to &[] (or str) AutoSlice, @@ -511,6 +521,8 @@ impl param_ty : to_bytes::IterBytes { /// Representation of regions: #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions @@ -540,6 +552,8 @@ enum region { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum bound_region { /// The self region for classes, impls (&T in a type defn or &self/T) br_self, @@ -671,6 +685,8 @@ enum IntVid = uint; enum FnVid = uint; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum RegionVid = uint; enum InferTy { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 7cb04bc0ea3c..027a1d067423 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -77,6 +77,8 @@ export provided_methods_map; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum method_origin { // fully statically resolved method method_static(ast::def_id), @@ -95,6 +97,8 @@ enum method_origin { // with a bounded trait. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type method_param = { // the trait containing the method to be invoked trait_id: ast::def_id, From 5b415c73723d33df735e2688515c3354975133cc Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 11:59:51 -0700 Subject: [PATCH 031/292] Revert bogus snapshot.py change --- src/etc/snapshot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/etc/snapshot.py b/src/etc/snapshot.py index dbf13454203d..b38294d5405a 100644 --- a/src/etc/snapshot.py +++ b/src/etc/snapshot.py @@ -68,8 +68,7 @@ def parse_line(n, line): match = re.match(r"([ST]) (\d{4}-\d{2}-\d{2}) ([a-fA-F\d]+)\s*$", line); if (not match): - raise Exception("%s:%d:%s:E syntax error: line = %s" - % (snapshotfile, n, hash, line)) + raise Exception("%s:%d:E syntax error: " % (snapshotfile, n)) return {"type": "snapshot", "date": match.group(2), "rev": match.group(3)} From a477c5af203e75cced729e85f9b54e8f2516502e Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 13:11:16 -0700 Subject: [PATCH 032/292] Revert "cap-clause-use-after-move: modernize error msg" This reverts commit bbda995bfe03680b6d621c6ab809ddb145125c3a. --- src/test/compile-fail/cap-clause-use-after-move.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/compile-fail/cap-clause-use-after-move.rs b/src/test/compile-fail/cap-clause-use-after-move.rs index 6946419ac9cd..7fb06ba5a23a 100644 --- a/src/test/compile-fail/cap-clause-use-after-move.rs +++ b/src/test/compile-fail/cap-clause-use-after-move.rs @@ -1,5 +1,7 @@ +// error-pattern:Unsatisfied precondition constraint + fn main() { let x = 5; let _y = fn~(move x) { }; - let _z = x; //~ ERROR use of moved variable: `x` + let _z = x; //< error: Unsatisfied precondition constraint } From 6ced454b96d95bee5b4925bb522ba629bd9cd715 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 8 Oct 2012 07:05:01 -0700 Subject: [PATCH 033/292] libcore: add pop/swap/consume to SendMap --- src/libcore/send_map.rs | 159 ++++++++++++++++++++++++++++++++-------- 1 file changed, 128 insertions(+), 31 deletions(-) diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs index 4a56ee5b8968..d275069a14b5 100644 --- a/src/libcore/send_map.rs +++ b/src/libcore/send_map.rs @@ -17,6 +17,9 @@ pub trait SendMap { fn insert(&mut self, k: K, +v: V) -> bool; fn remove(&mut self, k: &K) -> bool; + fn pop(&mut self, k: &K) -> Option; + fn swap(&mut self, k: K, +v: V) -> Option; + fn consume(&mut self, f: fn(K, V)); fn clear(&mut self); pure fn len(&const self) -> uint; pure fn is_empty(&const self) -> bool; @@ -198,6 +201,52 @@ pub mod linear { } } + fn pop_internal(&mut self, hash: uint, k: &K) -> Option { + // Removing from an open-addressed hashtable + // is, well, painful. The problem is that + // the entry may lie on the probe path for other + // entries, so removing it would make you think that + // those probe paths are empty. + // + // To address this we basically have to keep walking, + // re-inserting entries we find until we reach an empty + // bucket. We know we will eventually reach one because + // we insert one ourselves at the beginning (the removed + // entry). + // + // I found this explanation elucidating: + // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf + let mut idx = match self.bucket_for_key_with_hash(self.buckets, + hash, k) { + TableFull | FoundHole(_) => return None, + FoundEntry(idx) => idx + }; + + let len_buckets = self.buckets.len(); + let mut bucket = None; + self.buckets[idx] <-> bucket; + + let value = match move bucket { + None => None, + Some(move bucket) => { + let Bucket { value: move value, _ } = move bucket; + Some(value) + }, + }; + + idx = self.next_bucket(idx, len_buckets); + while self.buckets[idx].is_some() { + let mut bucket = None; + bucket <-> self.buckets[idx]; + self.insert_opt_bucket(move bucket); + idx = self.next_bucket(idx, len_buckets); + } + self.size -= 1; + + value + + } + fn search(&self, hash: uint, op: fn(x: &Option>) -> bool) { @@ -222,37 +271,55 @@ pub mod linear { } fn remove(&mut self, k: &K) -> bool { - // Removing from an open-addressed hashtable - // is, well, painful. The problem is that - // the entry may lie on the probe path for other - // entries, so removing it would make you think that - // those probe paths are empty. - // - // To address this we basically have to keep walking, - // re-inserting entries we find until we reach an empty - // bucket. We know we will eventually reach one because - // we insert one ourselves at the beginning (the removed - // entry). - // - // I found this explanation elucidating: - // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf - - let mut idx = match self.bucket_for_key(self.buckets, k) { - TableFull | FoundHole(_) => return false, - FoundEntry(idx) => idx - }; - - let len_buckets = self.buckets.len(); - self.buckets[idx] = None; - idx = self.next_bucket(idx, len_buckets); - while self.buckets[idx].is_some() { - let mut bucket = None; - bucket <-> self.buckets[idx]; - self.insert_opt_bucket(move bucket); - idx = self.next_bucket(idx, len_buckets); + match self.pop(k) { + Some(_) => true, + None => false, + } + } + + fn pop(&mut self, k: &K) -> Option { + let hash = k.hash_keyed(self.k0, self.k1) as uint; + self.pop_internal(hash, k) + } + + fn swap(&mut self, k: K, v: V) -> Option { + // this could be faster. + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let old_value = self.pop_internal(hash, &k); + + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + self.insert_internal(hash, k, v); + + old_value + } + + fn consume(&mut self, f: fn(K, V)) { + let mut buckets = ~[]; + self.buckets <-> buckets; + self.size = 0; + + do vec::consume(buckets) |_i, bucket| { + match move bucket { + None => { }, + Some(move bucket) => { + let Bucket { + key: move key, + value: move value, + _ + } = move bucket; + f(key, value) + } + } } - self.size -= 1; - return true; } fn clear(&mut self) { @@ -350,7 +417,6 @@ pub mod linear { } option::unwrap(move value) } - } } @@ -407,6 +473,37 @@ pub mod test { assert m.is_empty(); } + #[test] + pub fn pops() { + let mut m = ~LinearMap(); + m.insert(1, 2); + assert m.pop(&1) == Some(2); + assert m.pop(&1) == None; + } + + #[test] + pub fn swaps() { + let mut m = ~LinearMap(); + assert m.swap(1, 2) == None; + assert m.swap(1, 3) == Some(2); + assert m.swap(1, 4) == Some(3); + } + + #[test] + pub fn consumes() { + let mut m = ~LinearMap(); + assert m.insert(1, 2); + assert m.insert(2, 3); + let mut m2 = ~LinearMap(); + do m.consume |k, v| { + m2.insert(k, v); + } + assert m.len() == 0; + assert m2.len() == 2; + assert m2.find(&1) == Some(2); + assert m2.find(&2) == Some(3); + } + #[test] pub fn iterate() { let mut m = linear::linear_map_with_capacity(4); From 4c968f47e0df71d78c4c02f1e8fa008be70661c7 Mon Sep 17 00:00:00 2001 From: tav Date: Tue, 9 Oct 2012 01:24:54 +0100 Subject: [PATCH 034/292] doc: Remove duplicate word typo in the tutorial. --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 36b118a21a37..d49fcf92cabe 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -965,7 +965,7 @@ s.draw(); ~~~ This defines an _implementation_ for `Shape` containing a single -method, `draw`. In most most respects the `draw` method is defined +method, `draw`. In most respects the `draw` method is defined like any other function, with the exception of the name `self`. `self` is a special value that is automatically defined in each method, referring to the value being operated on. If we wanted we could add From 48495f9f7f1fb34bf0585d9d386592c95b5284d8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 17:33:03 -0700 Subject: [PATCH 035/292] Register snapshots --- src/snapshots.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/snapshots.txt b/src/snapshots.txt index 6037a2d49583..d00a037a0f12 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,11 @@ +S 2012-10-08 a477c5a + macos-i386 c059c3d5bd113f7edec48a4c2128f4b6138c3db8 + macos-x86_64 f121f4e2d831434f7825f72f3d328c11b13a522f + freebsd-x86_64 7f0de8feefc13267cbdebd299adc6b06f832cb9f + linux-i386 5975e794e5939034516fe888b70b532d34327bb2 + linux-x86_64 6dd88754f170f85d268e9430f7728efe43522383 + winnt-i386 76655d202b59c9b61cae860110ad5d0ca6e12cbf + S 2012-10-07 d301dd3 macos-i386 c9dfce9f231f22969b7e7995c1f39fcf86f81b2b macos-x86_64 3b1f6fd43fe03d7af334eeb111bc384428c4cd3d From 22efa39382d41b084fde1719df7ae8ce5697d8c9 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 8 Oct 2012 17:34:16 -0700 Subject: [PATCH 036/292] Revert "Revert "Remove old auto_serialize2 code (needs snapshot)"" This reverts commit a33535e441dc5461fec0489069a1491367ad1c91. --- src/libsyntax/ast.rs | 170 ----- src/libsyntax/ast_util.rs | 2 - src/libsyntax/ext/auto_serialize2.rs | 991 --------------------------- src/libsyntax/ext/base.rs | 61 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/parse/token.rs | 6 - src/libsyntax/syntax.rc | 3 - src/rustc/middle/freevars.rs | 2 - src/rustc/middle/ty.rs | 16 - src/rustc/middle/typeck.rs | 4 - 10 files changed, 2 insertions(+), 1255 deletions(-) delete mode 100644 src/libsyntax/ext/auto_serialize2.rs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f3e118461e66..a27336097d0c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -20,8 +20,6 @@ impl span: Deserializable { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type spanned = {node: T, span: span}; @@ -78,8 +76,6 @@ type fn_ident = Option; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type path = {span: span, global: bool, idents: ~[ident], @@ -92,8 +88,6 @@ type node_id = int; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type def_id = {crate: crate_num, node: node_id}; impl def_id : cmp::Eq { @@ -108,8 +102,6 @@ const crate_node_id: node_id = 0; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum ty_param_bound { bound_copy, bound_send, @@ -120,14 +112,10 @@ enum ty_param_bound { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum def { def_fn(def_id, purity), def_static_method(def_id, purity), @@ -308,8 +296,6 @@ type meta_item = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum meta_item_ { meta_word(~str), meta_list(~str, ~[@meta_item]), @@ -320,8 +306,6 @@ type blk = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type blk_ = {view_items: ~[@view_item], stmts: ~[@stmt], expr: Option<@expr>, @@ -330,20 +314,14 @@ type blk_ = {view_items: ~[@view_item], #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type pat = {id: node_id, node: pat_, span: span}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type field_pat = {ident: ident, pat: @pat}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum binding_mode { bind_by_value, bind_by_move, @@ -401,8 +379,6 @@ impl binding_mode : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -427,8 +403,6 @@ enum pat_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum mutability { m_mutbl, m_imm, m_const, } impl mutability : to_bytes::IterBytes { @@ -446,8 +420,6 @@ impl mutability : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum proto { proto_bare, // foreign fn proto_uniq, // fn~ @@ -464,8 +436,6 @@ impl proto : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -476,8 +446,6 @@ enum vstore { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum expr_vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) expr_vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -495,8 +463,6 @@ pure fn is_blockish(p: ast::proto) -> bool { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum binop { add, subtract, @@ -527,8 +493,6 @@ impl binop : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum unop { box(mutability), uniq(mutability), @@ -581,8 +545,6 @@ impl unop : cmp::Eq { // using ty::resolved_T(...). #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum inferable { expl(T), infer(node_id) @@ -623,8 +585,6 @@ impl inferable : cmp::Eq { // "resolved" mode: the real modes. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum rmode { by_ref, by_val, by_move, by_copy } impl rmode : to_bytes::IterBytes { @@ -648,8 +608,6 @@ type stmt = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum stmt_ { stmt_decl(@decl, node_id), @@ -662,8 +620,6 @@ enum stmt_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum init_op { init_assign, init_move, } impl init_op : cmp::Eq { @@ -688,16 +644,12 @@ impl init_op : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type initializer = {op: init_op, expr: @expr}; // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type local_ = {is_mutbl: bool, ty: @ty, pat: @pat, init: Option, id: node_id}; @@ -707,28 +659,20 @@ type decl = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum decl_ { decl_local(~[@local]), decl_item(@item), } #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type field_ = {mutbl: mutability, ident: ident, expr: @expr}; type field = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum blk_check_mode { default_blk, unsafe_blk, } impl blk_check_mode : cmp::Eq { @@ -745,28 +689,20 @@ impl blk_check_mode : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type expr = {id: node_id, callee_id: node_id, node: expr_, span: span}; // Extra node ID is only used for index, assign_op, unary, binary #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum log_level { error, debug, other } // 0 = error, 1 = debug, 2 = other #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum alt_mode { alt_check, alt_exhaustive, } #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum expr_ { expr_vstore(@expr, expr_vstore), expr_vec(~[@expr], mutability), @@ -824,8 +760,6 @@ enum expr_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type capture_item_ = { id: int, is_move: bool, @@ -855,8 +789,6 @@ type capture_clause = @~[capture_item]; // #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] #[doc="For macro invocations; parsing is delegated to the macro"] enum token_tree { tt_tok(span, token::token), @@ -922,8 +854,6 @@ type matcher = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum matcher_ { // match one token match_tok(token::token), @@ -940,16 +870,12 @@ type mac_arg = Option<@expr>; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type mac_body_ = {span: span}; type mac_body = Option; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum mac_ { mac_invoc(@path, mac_arg, mac_body), // old macro-invocation mac_invoc_tt(@path,~[token_tree]), // new macro-invocation @@ -964,8 +890,6 @@ type lit = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum lit_ { lit_str(@~str), lit_int(i64, int_ty), @@ -1008,30 +932,22 @@ impl ast::lit_: cmp::Eq { // type structure in middle/ty.rs as well. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type mt = {ty: @ty, mutbl: mutability}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type ty_field_ = {ident: ident, mt: mt}; type ty_field = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type ty_method = {ident: ident, attrs: ~[attribute], purity: purity, decl: fn_decl, tps: ~[ty_param], self_ty: self_ty, id: node_id, span: span}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] // A trait method is either required (meaning it doesn't have an // implementation, just a signature) or provided (meaning it has a default // implementation). @@ -1042,8 +958,6 @@ enum trait_method { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } impl int_ty : to_bytes::IterBytes { @@ -1074,8 +988,6 @@ impl int_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } impl uint_ty : to_bytes::IterBytes { @@ -1104,8 +1016,6 @@ impl uint_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum float_ty { ty_f, ty_f32, ty_f64, } impl float_ty : to_bytes::IterBytes { @@ -1125,15 +1035,11 @@ impl float_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type ty = {id: node_id, node: ty_, span: span}; // Not represented directly in the AST, referred to by name through a ty_path. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum prim_ty { ty_int(int_ty), ty_uint(uint_ty), @@ -1182,14 +1088,10 @@ impl prim_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type region = {id: node_id, node: region_}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum region_ { re_anon, re_static, @@ -1199,8 +1101,6 @@ enum region_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -1241,14 +1141,10 @@ impl ty : to_bytes::IterBytes { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type fn_decl = {inputs: ~[arg], output: @ty, @@ -1256,8 +1152,6 @@ type fn_decl = #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum purity { pure_fn, // declared with "pure fn" unsafe_fn, // declared with "unsafe fn" @@ -1280,8 +1174,6 @@ impl purity : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum ret_style { noreturn, // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) @@ -1308,8 +1200,6 @@ impl ret_style : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum self_ty_ { sty_static, // no self: static method sty_by_ref, // old by-reference self: `` @@ -1367,8 +1257,6 @@ type self_ty = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type method = {ident: ident, attrs: ~[attribute], tps: ~[ty_param], self_ty: self_ty, purity: purity, decl: fn_decl, body: blk, @@ -1377,14 +1265,10 @@ type method = {ident: ident, attrs: ~[attribute], #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type _mod = {view_items: ~[@view_item], items: ~[@item]}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum foreign_abi { foreign_abi_rust_intrinsic, foreign_abi_cdecl, @@ -1394,8 +1278,6 @@ enum foreign_abi { // Foreign mods can be named or anonymous #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum foreign_mod_sort { named, anonymous } impl foreign_mod_sort : cmp::Eq { @@ -1421,8 +1303,6 @@ impl foreign_abi : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type foreign_mod = {sort: foreign_mod_sort, view_items: ~[@view_item], @@ -1430,14 +1310,10 @@ type foreign_mod = #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type variant_arg = {ty: @ty, id: node_id}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum variant_kind { tuple_variant_kind(~[variant_arg]), struct_variant_kind(@struct_def), @@ -1446,20 +1322,14 @@ enum variant_kind { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type enum_def_ = { variants: ~[variant], common: Option<@struct_def> }; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum enum_def = enum_def_; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, id: node_id, disr_expr: Option<@expr>, vis: visibility}; @@ -1467,16 +1337,12 @@ type variant = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type path_list_ident_ = {name: ident, id: node_id}; type path_list_ident = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum namespace { module_ns, type_value_ns } impl namespace : cmp::Eq { @@ -1490,8 +1356,6 @@ type view_path = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum view_path_ { // quux = foo::bar::baz @@ -1510,15 +1374,11 @@ enum view_path_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type view_item = {node: view_item_, attrs: ~[attribute], vis: visibility, span: span}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum view_item_ { view_item_use(ident, ~[@meta_item], node_id), view_item_import(~[@view_path]), @@ -1533,8 +1393,6 @@ type attribute = spanned; // distinguished for pretty-printing. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum attr_style { attr_outer, attr_inner, } impl attr_style : cmp::Eq { @@ -1547,8 +1405,6 @@ impl attr_style : cmp::Eq { // doc-comments are promoted to attributes that have is_sugared_doc = true #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; /* @@ -1562,14 +1418,10 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; */ #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum visibility { public, private, inherited } impl visibility : cmp::Eq { @@ -1588,8 +1440,6 @@ impl visibility : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type struct_field_ = { kind: struct_field_kind, id: node_id, @@ -1600,8 +1450,6 @@ type struct_field = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum struct_field_kind { named_field(ident, class_mutability, visibility), unnamed_field // element of a tuple-like struct @@ -1609,8 +1457,6 @@ enum struct_field_kind { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type struct_def = { traits: ~[@trait_ref], /* traits this struct implements */ fields: ~[@struct_field], /* fields */ @@ -1628,16 +1474,12 @@ type struct_def = { */ #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type item = {ident: ident, attrs: ~[attribute], id: node_id, node: item_, vis: visibility, span: span}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum item_ { item_const(@ty, @expr), item_fn(fn_decl, purity, ~[ty_param], blk), @@ -1656,8 +1498,6 @@ enum item_ { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum class_mutability { class_mutable, class_immutable } impl class_mutability : to_bytes::IterBytes { @@ -1682,8 +1522,6 @@ type class_ctor = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type class_ctor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, @@ -1694,8 +1532,6 @@ type class_dtor = spanned; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type class_dtor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, @@ -1703,8 +1539,6 @@ type class_dtor_ = {id: node_id, #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type foreign_item = {ident: ident, attrs: ~[attribute], @@ -1715,8 +1549,6 @@ type foreign_item = #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum foreign_item_ { foreign_item_fn(fn_decl, purity, ~[ty_param]), foreign_item_const(@ty) @@ -1727,8 +1559,6 @@ enum foreign_item_ { // that we trans. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 897a51f710c6..ab24d7a53160 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -408,8 +408,6 @@ fn dtor_dec() -> fn_decl { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type id_range = {min: node_id, max: node_id}; fn empty(range: id_range) -> bool { diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs deleted file mode 100644 index b3102f8b4f72..000000000000 --- a/src/libsyntax/ext/auto_serialize2.rs +++ /dev/null @@ -1,991 +0,0 @@ -/* - -The compiler code necessary to implement the #[auto_serialize2] and -#[auto_deserialize2] extension. The idea here is that type-defining items may -be tagged with #[auto_serialize2] and #[auto_deserialize2], which will cause -us to generate a little companion module with the same name as the item. - -For example, a type like: - - #[auto_serialize2] - #[auto_deserialize2] - struct Node {id: uint} - -would generate two implementations like: - - impl Node: Serializable { - fn serialize(s: &S) { - do s.emit_struct("Node") { - s.emit_field("id", 0, || s.emit_uint(self)) - } - } - } - - impl node_id: Deserializable { - static fn deserialize(d: &D) -> Node { - do d.read_struct("Node") { - Node { - id: d.read_field(~"x", 0, || deserialize(d)) - } - } - } - } - -Other interesting scenarios are whe the item has type parameters or -references other non-built-in types. A type definition like: - - #[auto_serialize2] - #[auto_deserialize2] - type spanned = {node: T, span: span}; - -would yield functions like: - - impl spanned: Serializable { - fn serialize(s: &S) { - do s.emit_rec { - s.emit_field("node", 0, || self.node.serialize(s)); - s.emit_field("span", 1, || self.span.serialize(s)); - } - } - } - - impl spanned: Deserializable { - static fn deserialize(d: &D) -> spanned { - do d.read_rec { - { - node: d.read_field(~"node", 0, || deserialize(d)), - span: d.read_field(~"span", 1, || deserialize(d)), - } - } - } - } - -FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the -standard library. - -Misc notes: ------------ - -I use move mode arguments for ast nodes that will get inserted as is -into the tree. This is intended to prevent us from inserting the same -node twice. - -*/ - -use base::*; -use codemap::span; -use std::map; -use std::map::HashMap; - -export expand_auto_serialize; -export expand_auto_deserialize; - -// Transitional reexports so qquote can find the paths it is looking for -mod syntax { - pub use ext; - pub use parse; -} - -fn expand_auto_serialize( - cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - fn is_auto_serialize2(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) == ~"auto_serialize2" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize2(a)), - .. *item} - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_serialize2) { - match item.node { - ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { - let ser_impl = mk_rec_ser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_class(@{ fields, _}, tps) => { - let ser_impl = mk_struct_ser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_enum(enum_def, tps) => { - let ser_impl = mk_enum_ser_impl( - cx, - item.span, - item.ident, - enum_def, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_serialize2] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -fn expand_auto_deserialize( - cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - fn is_auto_deserialize2(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) == ~"auto_deserialize2" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize2(a)), - .. *item} - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_deserialize2) { - match item.node { - ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { - let deser_impl = mk_rec_deser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_class(@{ fields, _}, tps) => { - let deser_impl = mk_struct_deser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_enum(enum_def, tps) => { - let deser_impl = mk_enum_deser_impl( - cx, - item.span, - item.ident, - enum_def, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_deserialize2] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -fn mk_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - path: @ast::path, - tps: ~[ast::ty_param], - f: fn(@ast::ty) -> @ast::method -) -> @ast::item { - // All the type parameters need to bound to the trait. - let trait_tps = do tps.map |tp| { - let t_bound = ast::bound_trait(@{ - id: cx.next_id(), - node: ast::ty_path(path, cx.next_id()), - span: span, - }); - - { - ident: tp.ident, - id: cx.next_id(), - bounds: @vec::append(~[t_bound], *tp.bounds) - } - }; - - let opt_trait = Some(@{ - path: path, - ref_id: cx.next_id(), - impl_id: cx.next_id(), - }); - - let ty = cx.ty_path( - span, - ~[ident], - tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) - ); - - @{ - // This is a new-style impl declaration. - // XXX: clownshoes - ident: ast::token::special_idents::clownshoes_extensions, - attrs: ~[], - id: cx.next_id(), - node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), - vis: ast::public, - span: span, - } -} - -fn mk_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - tps: ~[ast::ty_param], - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialization2::Serializable trait. - let path = cx.path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Serializable"), - ] - ); - - mk_impl( - cx, - span, - ident, - path, - tps, - |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) - ) -} - -fn mk_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - tps: ~[ast::ty_param], - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialization2::Deserializable trait. - let path = cx.path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Deserializable"), - ] - ); - - mk_impl( - cx, - span, - ident, - path, - tps, - |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) - ) -} - -fn mk_ser_method( - cx: ext_ctxt, - span: span, - ser_body: ast::blk -) -> @ast::method { - let ser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Serializer"), - ], - ~[] - ); - - let ser_tps = ~[{ - ident: cx.ident_of(~"__S"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(ser_bound)], - }]; - - let ty_s = @{ - id: cx.next_id(), - node: ast::ty_rptr( - @{ - id: cx.next_id(), - node: ast::re_anon, - }, - { - ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), - mutbl: ast::m_imm - } - ), - span: span, - }; - - let ser_inputs = ~[{ - mode: ast::infer(cx.next_id()), - ty: ty_s, - ident: cx.ident_of(~"__s"), - id: cx.next_id(), - }]; - - let ser_output = @{ - id: cx.next_id(), - node: ast::ty_nil, - span: span, - }; - - let ser_decl = { - inputs: ser_inputs, - output: ser_output, - cf: ast::return_val, - }; - - @{ - ident: cx.ident_of(~"serialize"), - attrs: ~[], - tps: ser_tps, - self_ty: { node: ast::sty_region(ast::m_imm), span: span }, - purity: ast::impure_fn, - decl: ser_decl, - body: ser_body, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: ast::public, - } -} - -fn mk_deser_method( - cx: ext_ctxt, - span: span, - ty: @ast::ty, - deser_body: ast::blk -) -> @ast::method { - let deser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Deserializer"), - ], - ~[] - ); - - let deser_tps = ~[{ - ident: cx.ident_of(~"__D"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(deser_bound)], - }]; - - let ty_d = @{ - id: cx.next_id(), - node: ast::ty_rptr( - @{ - id: cx.next_id(), - node: ast::re_anon, - }, - { - ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), - mutbl: ast::m_imm - } - ), - span: span, - }; - - let deser_inputs = ~[{ - mode: ast::infer(cx.next_id()), - ty: ty_d, - ident: cx.ident_of(~"__d"), - id: cx.next_id(), - }]; - - let deser_decl = { - inputs: deser_inputs, - output: ty, - cf: ast::return_val, - }; - - @{ - ident: cx.ident_of(~"deserialize"), - attrs: ~[], - tps: deser_tps, - self_ty: { node: ast::sty_static, span: span }, - purity: ast::impure_fn, - decl: deser_decl, - body: deser_body, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: ast::public, - } -} - -fn mk_rec_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[ast::ty_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); - - // ast for `__s.emit_rec(|| $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_rec") - ), - ~[cx.lambda_stmts(span, fields)] - ); - - mk_ser_impl(cx, span, ident, tps, body) -} - -fn mk_rec_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[ast::ty_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); - - // ast for `read_rec(|| $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_rec") - ), - ~[ - cx.lambda_expr( - cx.expr( - span, - ast::expr_rec(fields, None) - ) - ) - ] - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -fn mk_struct_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[@ast::struct_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); - - // ast for `__s.emit_struct($(name), || $(fields))` - let ser_body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_struct") - ), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lambda_stmts(span, fields), - ] - ); - - mk_ser_impl(cx, span, ident, tps, ser_body) -} - -fn mk_struct_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[@ast::struct_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); - - // ast for `read_struct($(name), || $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_struct") - ), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lambda_expr( - cx.expr( - span, - ast::expr_struct( - cx.path(span, ~[ident]), - fields, - None - ) - ) - ), - ] - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -// Records and structs don't have the same fields types, but they share enough -// that if we extract the right subfields out we can share the serialization -// generator code. -type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; - -fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { - do fields.map |field| { - { - span: field.span, - ident: field.node.ident, - mutbl: field.node.mt.mutbl, - } - } -} - -fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { - do fields.map |field| { - let (ident, mutbl) = match field.node.kind { - ast::named_field(ident, mutbl, _) => (ident, mutbl), - _ => fail ~"[auto_serialize2] does not support \ - unnamed fields", - }; - - { - span: field.span, - ident: ident, - mutbl: match mutbl { - ast::class_mutable => ast::m_mutbl, - ast::class_immutable => ast::m_imm, - }, - } - } -} - -fn mk_ser_fields( - cx: ext_ctxt, - span: span, - fields: ~[field] -) -> ~[@ast::stmt] { - do fields.mapi |idx, field| { - // ast for `|| self.$(name).serialize(__s)` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"self"), - field.ident - ), - cx.ident_of(~"serialize") - ), - ~[cx.expr_var(span, ~"__s")] - ) - ); - - // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` - cx.stmt( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_field") - ), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ) - ) - } -} - -fn mk_deser_fields( - cx: ext_ctxt, - span: span, - fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] -) -> ~[ast::field] { - do fields.mapi |idx, field| { - // ast for `|| std::serialization2::deserialize(__d)` - let expr_lambda = cx.lambda( - cx.expr_blk( - cx.expr_call( - span, - cx.expr_path(span, ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"deserialize"), - ]), - ~[cx.expr_var(span, ~"__d")] - ) - ) - ); - - // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` - let expr: @ast::expr = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_field") - ), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ); - - { - node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, - span: span, - } - } -} - -fn mk_enum_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - tps: ~[ast::ty_param] -) -> @ast::item { - let body = mk_enum_ser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_ser_impl(cx, span, ident, tps, body) -} - -fn mk_enum_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - tps: ~[ast::ty_param] -) -> @ast::item { - let body = mk_enum_deser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -fn ser_variant( - cx: ext_ctxt, - span: span, - v_name: ast::ident, - v_idx: uint, - args: ~[ast::variant_arg] -) -> ast::arm { - // Name the variant arguments. - let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); - - // Bind the names to the variant argument type. - let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); - - let pat_node = if pats.is_empty() { - ast::pat_ident( - ast::bind_by_implicit_ref, - cx.path(span, ~[v_name]), - None - ) - } else { - ast::pat_enum( - cx.path(span, ~[v_name]), - Some(pats) - ) - }; - - let pat = @{ - id: cx.next_id(), - node: pat_node, - span: span, - }; - - let stmts = do args.mapi |a_idx, _arg| { - // ast for `__s.emit_enum_variant_arg` - let expr_emit = cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum_variant_arg") - ); - - // ast for `|| $(v).serialize(__s)` - let expr_serialize = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_path(span, ~[names[a_idx]]), - cx.ident_of(~"serialize") - ), - ~[cx.expr_var(span, ~"__s")] - ) - ); - - // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` - cx.stmt( - cx.expr_call( - span, - expr_emit, - ~[cx.lit_uint(span, a_idx), expr_serialize] - ) - ) - }; - - // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum_variant") - ), - ~[ - cx.lit_str(span, @cx.str_of(v_name)), - cx.lit_uint(span, v_idx), - cx.lit_uint(span, stmts.len()), - cx.lambda_stmts(span, stmts), - ] - ); - - { pats: ~[pat], guard: None, body: cx.expr_blk(body) } -} - -fn mk_enum_ser_body( - cx: ext_ctxt, - span: span, - name: ast::ident, - variants: ~[ast::variant] -) -> @ast::expr { - let arms = do variants.mapi |v_idx, variant| { - match variant.node.kind { - ast::tuple_variant_kind(args) => - ser_variant(cx, span, variant.node.name, v_idx, args), - ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented", - ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented", - } - }; - - // ast for `match *self { $(arms) }` - let match_expr = cx.expr( - span, - ast::expr_match( - cx.expr( - span, - ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) - ), - arms - ) - ); - - // ast for `__s.emit_enum($(name), || $(match_expr))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum") - ), - ~[ - cx.lit_str(span, @cx.str_of(name)), - cx.lambda_expr(match_expr), - ] - ) -} - -fn mk_enum_deser_variant_nary( - cx: ext_ctxt, - span: span, - name: ast::ident, - args: ~[ast::variant_arg] -) -> @ast::expr { - let args = do args.mapi |idx, _arg| { - // ast for `|| std::serialization2::deserialize(__d)` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_path(span, ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"deserialize"), - ]), - ~[cx.expr_var(span, ~"__d")] - ) - ); - - // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum_variant_arg") - ), - ~[cx.lit_uint(span, idx), expr_lambda] - ) - }; - - // ast for `$(name)($(args))` - cx.expr_call(span, cx.expr_path(span, ~[name]), args) -} - -fn mk_enum_deser_body( - cx: ext_ctxt, - span: span, - name: ast::ident, - variants: ~[ast::variant] -) -> @ast::expr { - let mut arms = do variants.mapi |v_idx, variant| { - let body = match variant.node.kind { - ast::tuple_variant_kind(args) => { - if args.is_empty() { - // for a nullary variant v, do "v" - cx.expr_path(span, ~[variant.node.name]) - } else { - // for an n-ary variant v, do "v(a_1, ..., a_n)" - mk_enum_deser_variant_nary( - cx, - span, - variant.node.name, - args - ) - } - }, - ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented", - ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented", - }; - - let pat = @{ - id: cx.next_id(), - node: ast::pat_lit(cx.lit_uint(span, v_idx)), - span: span, - }; - - { - pats: ~[pat], - guard: None, - body: cx.expr_blk(body), - } - }; - - let impossible_case = { - pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], - guard: None, - - // FIXME(#3198): proper error message - body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), - }; - - arms.push(impossible_case); - - // ast for `|i| { match i { $(arms) } }` - let expr_lambda = cx.expr( - span, - ast::expr_fn_block( - { - inputs: ~[{ - mode: ast::infer(cx.next_id()), - ty: @{ - id: cx.next_id(), - node: ast::ty_infer, - span: span - }, - ident: cx.ident_of(~"i"), - id: cx.next_id(), - }], - output: @{ - id: cx.next_id(), - node: ast::ty_infer, - span: span, - }, - cf: ast::return_val, - }, - cx.expr_blk( - cx.expr( - span, - ast::expr_match(cx.expr_var(span, ~"i"), arms) - ) - ), - @~[] - ) - ); - - // ast for `__d.read_enum_variant($(expr_lambda))` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum_variant") - ), - ~[expr_lambda] - ) - ); - - // ast for `__d.read_enum($(e_name), $(expr_lambda))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum") - ), - ~[ - cx.lit_str(span, @cx.str_of(name)), - expr_lambda - ] - ) -} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index ab56b6bb322e..c106042b9a3d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -54,7 +54,7 @@ enum syntax_extension { // macro_defining() is obsolete, remove when #old_macros go away. macro_defining(macro_definer), - // #[auto_serialize2] and such. will probably survive death of #old_macros + // #[auto_serialize] and such. will probably survive death of #old_macros item_decorator(item_decorator), // Token-tree expanders @@ -64,65 +64,6 @@ enum syntax_extension { // A temporary hard-coded map of methods for expanding syntax extension // AST nodes into full ASTs -#[cfg(stage0)] -fn syntax_expander_table() -> HashMap<~str, syntax_extension> { - fn builtin(f: syntax_expander_) -> syntax_extension - {normal({expander: f, span: None})} - fn builtin_expr_tt(f: syntax_expander_tt_) -> syntax_extension { - expr_tt({expander: f, span: None}) - } - fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension { - item_tt({expander: f, span: None}) - } - let syntax_expanders = HashMap(); - syntax_expanders.insert(~"macro", - macro_defining(ext::simplext::add_new_extension)); - syntax_expanders.insert(~"macro_rules", - builtin_item_tt( - ext::tt::macro_rules::add_new_extension)); - syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); - syntax_expanders.insert( - ~"auto_serialize2", - item_decorator(ext::auto_serialize2::expand_auto_serialize)); - syntax_expanders.insert( - ~"auto_deserialize2", - item_decorator(ext::auto_serialize2::expand_auto_deserialize)); - syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext)); - syntax_expanders.insert(~"concat_idents", - builtin(ext::concat_idents::expand_syntax_ext)); - syntax_expanders.insert(~"ident_to_str", - builtin(ext::ident_to_str::expand_syntax_ext)); - syntax_expanders.insert(~"log_syntax", - builtin_expr_tt( - ext::log_syntax::expand_syntax_ext)); - syntax_expanders.insert(~"ast", - builtin(ext::qquote::expand_ast)); - syntax_expanders.insert(~"line", - builtin(ext::source_util::expand_line)); - syntax_expanders.insert(~"col", - builtin(ext::source_util::expand_col)); - syntax_expanders.insert(~"file", - builtin(ext::source_util::expand_file)); - syntax_expanders.insert(~"stringify", - builtin(ext::source_util::expand_stringify)); - syntax_expanders.insert(~"include", - builtin(ext::source_util::expand_include)); - syntax_expanders.insert(~"include_str", - builtin(ext::source_util::expand_include_str)); - syntax_expanders.insert(~"include_bin", - builtin(ext::source_util::expand_include_bin)); - syntax_expanders.insert(~"module_path", - builtin(ext::source_util::expand_mod)); - syntax_expanders.insert(~"proto", - builtin_item_tt(ext::pipes::expand_proto)); - syntax_expanders.insert( - ~"trace_macros", - builtin_expr_tt(ext::trace_macros::expand_trace_macros)); - return syntax_expanders; -} - -#[cfg(stage1)] -#[cfg(stage2)] fn syntax_expander_table() -> HashMap<~str, syntax_extension> { fn builtin(f: syntax_expander_) -> syntax_extension {normal({expander: f, span: None})} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2d0b2f4c80ab..22e2cfcde6b5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -124,7 +124,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, } // This is a secondary mechanism for invoking syntax extensions on items: -// "decorator" attributes, such as #[auto_serialize2]. These are invoked by an +// "decorator" attributes, such as #[auto_serialize]. These are invoked by an // attribute prefixing an item, and are interpreted by feeding the item // through the named attribute _as a syntax extension_ and splicing in the // resulting item vec into place in favour of the decorator. Note that diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index b63260997f75..dce4dc3bbc7b 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -4,8 +4,6 @@ use std::map::HashMap; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum binop { PLUS, MINUS, @@ -21,8 +19,6 @@ enum binop { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum token { /* Expression-operator symbols. */ EQ, @@ -81,8 +77,6 @@ enum token { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] /// For interpolation during macro expansion. enum nonterminal { nt_item(@ast::item), diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 4c29fc5512a7..93ed5bd471bc 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -130,9 +130,6 @@ mod ext { mod log_syntax; #[legacy_exports] mod auto_serialize; - #[cfg(stage0)] - #[legacy_exports] - mod auto_serialize2; #[legacy_exports] mod source_util; diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index 28400b5455d5..1b42c9bb4b67 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -18,8 +18,6 @@ export has_freevars; // (The def_upvar will already have been stripped). #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type freevar_entry = { def: ast::def, //< The variable being accessed free. span: span //< First span where it is accessed (there can be multiple) diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 85f03e1f0b33..ca41be6f9d0a 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -213,8 +213,6 @@ type mt = {ty: t, mutbl: ast::mutability}; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum vstore { vstore_fixed(uint), vstore_uniq, @@ -275,8 +273,6 @@ type opt_region_variance = Option; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum region_variance { rv_covariant, rv_invariant, rv_contravariant } impl region_variance : cmp::Eq { @@ -295,8 +291,6 @@ impl region_variance : cmp::Eq { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type AutoAdjustment = { autoderefs: uint, autoref: Option @@ -304,8 +298,6 @@ type AutoAdjustment = { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type AutoRef = { kind: AutoRefKind, region: region, @@ -314,8 +306,6 @@ type AutoRef = { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum AutoRefKind { /// Convert from @[]/~[] to &[] (or str) AutoSlice, @@ -521,8 +511,6 @@ impl param_ty : to_bytes::IterBytes { /// Representation of regions: #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions @@ -552,8 +540,6 @@ enum region { #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum bound_region { /// The self region for classes, impls (&T in a type defn or &self/T) br_self, @@ -685,8 +671,6 @@ enum IntVid = uint; enum FnVid = uint; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum RegionVid = uint; enum InferTy { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 027a1d067423..7cb04bc0ea3c 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -77,8 +77,6 @@ export provided_methods_map; #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] enum method_origin { // fully statically resolved method method_static(ast::def_id), @@ -97,8 +95,6 @@ enum method_origin { // with a bounded trait. #[auto_serialize] #[auto_deserialize] -#[auto_serialize2] -#[auto_deserialize2] type method_param = { // the trait containing the method to be invoked trait_id: ast::def_id, From bdc1b7a8a71b0168a26e1f897246abc6c6ab1091 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 9 Oct 2012 08:36:06 -0700 Subject: [PATCH 037/292] libcore: add a str::with_capacity to match the fn in vec --- src/libcore/str.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d743f0c7f3be..33016bf9923e 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1473,6 +1473,11 @@ pub pure fn from_utf16(v: &[u16]) -> ~str { move buf } +pub pure fn with_capacity(capacity: uint) -> ~str { + let mut buf = ~""; + unsafe { reserve(&mut buf, capacity); } + move buf +} /** * As char_len but for a slice of a string From 0aa42bc91e08faac450d1850f3b549b78382ccf4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 9 Oct 2012 14:40:23 -0700 Subject: [PATCH 038/292] Copyedit the macro tutorial I hope I haven't introduced any grievous errors :-) --- doc/tutorial-macros.md | 117 +++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 44 deletions(-) diff --git a/doc/tutorial-macros.md b/doc/tutorial-macros.md index 8202fbe8dc53..31f260076f00 100644 --- a/doc/tutorial-macros.md +++ b/doc/tutorial-macros.md @@ -2,10 +2,11 @@ # Introduction -Functions are the programmer's primary tool of abstraction, but there are -cases in which they are insufficient, because the programmer wants to -abstract over concepts not represented as values. Consider the following -example: +Functions are the primary tool that programmers can use to build +abstractions. Sometimes, though, programmers want to abstract over +compile-time, syntactic structures rather than runtime values. For example, +the following two code fragments both pattern-match on their input and return +early in one case, doing nothing otherwise: ~~~~ # enum t { special_a(uint), special_b(uint) }; @@ -24,11 +25,12 @@ match input_2 { # } ~~~~ -This code could become tiresome if repeated many times. However, there is -no reasonable function that could be written to solve this problem. In such a -case, it's possible to define a macro to solve the problem. Macros are +This code could become tiresome if repeated many times. However, there is no +straightforward way to rewrite it without the repeated code, using functions +alone. There is a solution, though: defining a macro to solve the problem. Macros are lightweight custom syntax extensions, themselves defined using the -`macro_rules!` syntax extension: +`macro_rules!` syntax extension. The following `early_return` macro captures +the pattern in the above code: ~~~~ # enum t { special_a(uint), special_b(uint) }; @@ -42,7 +44,12 @@ macro_rules! early_return( } ); ); -// ... +~~~~ + +Now, we can replace each `match` with an invocation of the `early_return` +macro: + +~~~~ early_return!(input_1 special_a); // ... early_return!(input_2 special_b); @@ -50,48 +57,72 @@ early_return!(input_2 special_b); # } ~~~~ -Macros are defined in pattern-matching style: +Macros are defined in pattern-matching style: in the above example, the text +`($inp:expr $sp:ident)` that appears on the left-hand side of the `=>` is the +*macro invocation syntax*, a pattern denoting how to write a call to the +macro. The text on the right-hand side of the `=>`, beginning with `match +$inp`, is the *macro transcription syntax*: what the macro expands to. # Invocation syntax -On the left-hand-side of the `=>` is the macro invocation syntax. It is -free-form, excepting the following rules: +The macro invocation syntax specifies the syntax for the arguments to the +macro. It appears on the left-hand side of the `=>` in a macro definition. It +conforms to the following rules: -1. It must be surrounded in parentheses. +1. It must be surrounded by parentheses. 2. `$` has special meaning. 3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is forbidden. +Otherwise, the invocation syntax is free-form. + To take as an argument a fragment of Rust code, write `$` followed by a name - (for use on the right-hand side), followed by a `:`, followed by the sort of -fragment to match (the most common ones are `ident`, `expr`, `ty`, `pat`, and -`block`). Anything not preceded by a `$` is taken literally. The standard + (for use on the right-hand side), followed by a `:`, followed by a *fragment + specifier*. The fragment specifier denotes the sort of fragment to match. The + most common fragment specifiers are: + +* `ident` (an identifier, referring to a variable or item. Examples: `f`, `x`, + `foo`.) +* `expr` (an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`; + `f(42)`.) +* `ty` (a type. Examples: `int`, `~[(char, ~str)]`, `&T`.) +* `pat` (a pattern, usually appearing in a `match` or on the left-hand side of + a declaration. Examples: `Some(t)`; `(17, 'a')`; `_`.) +* `block` (a sequence of actions. Example: `{ log(error, "hi"); return 12; }`) + +The parser interprets any token that's not preceded by a `$` literally. Rust's usual rules of tokenization apply, -So `($x:ident => (($e:expr)))`, though excessively fancy, would create a macro -that could be invoked like `my_macro!(i=>(( 2+2 )))`. +So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a macro +that could be invoked like: `my_macro!(i->(( 2+2 )))`. # Transcription syntax The right-hand side of the `=>` follows the same rules as the left-hand side, -except that `$` need only be followed by the name of the syntactic fragment -to transcribe. +except that a `$` need only be followed by the name of the syntactic fragment +to transcribe into the macro expansion; its type need not be repeated. -The right-hand side must be surrounded by delimiters of some kind, and must be -an expression; currently, user-defined macros can only be invoked in -expression position (even though `macro_rules!` itself can be in item -position). +The right-hand side must be enclosed by delimiters, and must be +an expression. Currently, invocations of user-defined macros can only appear in a context +where the Rust grammar requires an expression, even though `macro_rules!` itself can appear +in a context where the grammar requires an item. # Multiplicity ## Invocation -Going back to the motivating example, suppose that we wanted each invocation -of `early_return` to potentially accept multiple "special" identifiers. The -syntax `$(...)*` accepts zero or more occurrences of its contents, much like -the Kleene star operator in regular expressions. It also supports a separator -token (a comma-separated list could be written `$(...),*`), and `+` instead of -`*` to mean "at least one". +Going back to the motivating example, recall that `early_return` expanded into +a `match` that would `return` if the `match`'s scrutinee matched the +"special case" identifier provided as the second argument to `early_return`, +and do nothing otherwise. Now suppose that we wanted to write a +version of `early_return` that could handle a variable number of "special" +cases. + +The syntax `$(...)*` on the left-hand side of the `=>` in a macro definition +accepts zero or more occurrences of its contents. It works much +like the `*` operator in regular expressions. It also supports a +separator token (a comma-separated list could be written `$(...),*`), and `+` +instead of `*` to mean "at least one". ~~~~ # enum t { special_a(uint),special_b(uint),special_c(uint),special_d(uint)}; @@ -118,37 +149,35 @@ early_return!(input_2, [special_b]); ### Transcription As the above example demonstrates, `$(...)*` is also valid on the right-hand -side of a macro definition. The behavior of Kleene star in transcription, -especially in cases where multiple stars are nested, and multiple different +side of a macro definition. The behavior of `*` in transcription, +especially in cases where multiple `*`s are nested, and multiple different names are involved, can seem somewhat magical and intuitive at first. The system that interprets them is called "Macro By Example". The two rules to keep in mind are (1) the behavior of `$(...)*` is to walk through one "layer" of repetitions for all of the `$name`s it contains in lockstep, and (2) each `$name` must be under at least as many `$(...)*`s as it was matched against. -If it is under more, it'll will be repeated, as appropriate. +If it is under more, it'll be repeated, as appropriate. ## Parsing limitations -The parser used by the macro system is reasonably powerful, but the parsing of -Rust syntax is restricted in two ways: +The macro parser will parse Rust syntax with two limitations: 1. The parser will always parse as much as possible. For example, if the comma were omitted from the syntax of `early_return!` above, `input_1 [` would've been interpreted as the beginning of an array index. In fact, invoking the macro would have been impossible. 2. The parser must have eliminated all ambiguity by the time it reaches a -`$name:fragment_specifier`. This most often affects them when they occur in -the beginning of, or immediately after, a `$(...)*`; requiring a distinctive +`$name:fragment_specifier` declaration. This limitation can result in parse +errors when declarations occur at the beginning of, or immediately after, +a `$(...)*`. Changing the invocation syntax to require a distinctive token in front can solve the problem. ## A final note Macros, as currently implemented, are not for the faint of heart. Even -ordinary syntax errors can be more difficult to debug when they occur inside -a macro, and errors caused by parse problems in generated code can be very +ordinary syntax errors can be more difficult to debug when they occur inside a +macro, and errors caused by parse problems in generated code can be very tricky. Invoking the `log_syntax!` macro can help elucidate intermediate -states, using `trace_macros!(true)` will automatically print those -intermediate states out, and using `--pretty expanded` as an argument to the -compiler will show the result of expansion. - - +states, invoking `trace_macros!(true)` will automatically print those +intermediate states out, and passing the flag `--pretty expanded` as a +command-line argument to the compiler will show the result of expansion. From 28cf16a30409463cbac3b7bb660be90dcecab06a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 9 Oct 2012 15:33:24 -0700 Subject: [PATCH 039/292] Fix tutorial breakage. --- doc/tutorial-macros.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/doc/tutorial-macros.md b/doc/tutorial-macros.md index 31f260076f00..995944b2fbd8 100644 --- a/doc/tutorial-macros.md +++ b/doc/tutorial-macros.md @@ -44,12 +44,7 @@ macro_rules! early_return( } ); ); -~~~~ - -Now, we can replace each `match` with an invocation of the `early_return` -macro: - -~~~~ +// ... early_return!(input_1 special_a); // ... early_return!(input_2 special_b); From 4b3be853afcf25a2801dea951e3d6d2ae7cba355 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 9 Oct 2012 16:14:55 -0700 Subject: [PATCH 040/292] Copyedit tasks tutorial --- doc/tutorial-tasks.md | 235 +++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 115 deletions(-) diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md index 1593184bce9f..8a0cda3e8207 100644 --- a/doc/tutorial-tasks.md +++ b/doc/tutorial-tasks.md @@ -2,38 +2,37 @@ # Introduction -The Rust language is designed from the ground up to support pervasive +The designers of Rust designed the language from the ground up to support pervasive and safe concurrency through lightweight, memory-isolated tasks and message passing. -Rust tasks are not the same as traditional threads - they are what are -often referred to as _green threads_, cooperatively scheduled by the -Rust runtime onto a small number of operating system threads. Being -significantly cheaper to create than traditional threads, Rust can -create hundreds of thousands of concurrent tasks on a typical 32-bit -system. +Rust tasks are not the same as traditional threads: rather, they are more like +_green threads_. The Rust runtime system schedules tasks cooperatively onto a +small number of operating system threads. Because tasks are significantly +cheaper to create than traditional threads, Rust can create hundreds of +thousands of concurrent tasks on a typical 32-bit system. -Tasks provide failure isolation and recovery. When an exception occurs -in rust code (either by calling `fail` explicitly or by otherwise performing -an invalid operation) the entire task is destroyed - there is no way -to `catch` an exception as in other languages. Instead tasks may monitor -each other to detect when failure has occurred. +Tasks provide failure isolation and recovery. When an exception occurs in Rust +code (as a result of an explicit call to `fail`, an assertion failure, or +another invalid operation), the runtime system destroys the entire +task. Unlike in languages such as Java and C++, there is no way to `catch` an +exception. Instead, tasks may monitor each other for failure. -Rust tasks have dynamically sized stacks. When a task is first created -it starts off with a small amount of stack (currently in the low -thousands of bytes, depending on platform) and more stack is acquired as -needed. A Rust task will never run off the end of the stack as is -possible in many other languages, but they do have a stack budget, and -if a Rust task exceeds its stack budget then it will fail safely. +Rust tasks have dynamically sized stacks. A task begins its life with a small +amount of stack space (currently in the low thousands of bytes, depending on +platform), and acquires more stack as needed. Unlike in languages such as C, a +Rust task cannot run off the end of the stack. However, tasks do have a stack +budget. If a Rust task exceeds its stack budget, then it will fail safely: +with a checked exception. -Tasks make use of Rust's type system to provide strong memory safety -guarantees, disallowing shared mutable state. Communication between -tasks is facilitated by the transfer of _owned_ data through the -global _exchange heap_. +Tasks use Rust's type system to provide strong memory safety guarantees. In +particular, the type system guarantees that tasks cannot share mutable state +with each other. Tasks communicate with each other by transferring _owned_ +data through the global _exchange heap_. -This tutorial will explain the basics of tasks and communication in Rust, -explore some typical patterns in concurrent Rust code, and finally -discuss some of the more exotic synchronization types in the standard +This tutorial explains the basics of tasks and communication in Rust, +explores some typical patterns in concurrent Rust code, and finally +discusses some of the more unusual synchronization types in the standard library. > ***Warning:*** This tutorial is incomplete @@ -45,23 +44,23 @@ and efficient tasks, all of the task functionality itself is implemented in the core and standard libraries, which are still under development and do not always present a consistent interface. -In particular, there are currently two independent modules that provide -a message passing interface to Rust code: `core::comm` and `core::pipes`. -`core::comm` is an older, less efficient system that is being phased out -in favor of `pipes`. At some point the existing `core::comm` API will -be removed and the user-facing portions of `core::pipes` will be moved -to `core::comm`. In this tutorial we will discuss `pipes` and ignore -the `comm` API. +In particular, there are currently two independent modules that provide a +message passing interface to Rust code: `core::comm` and `core::pipes`. +`core::comm` is an older, less efficient system that is being phased out in +favor of `pipes`. At some point, we will remove the existing `core::comm` API +and move the user-facing portions of `core::pipes` to `core::comm`. In this +tutorial, we discuss `pipes` and ignore the `comm` API. For your reference, these are the standard modules involved in Rust -concurrency at the moment. +concurrency at this writing. * [`core::task`] - All code relating to tasks and task scheduling * [`core::comm`] - The deprecated message passing API * [`core::pipes`] - The new message passing infrastructure and API * [`std::comm`] - Higher level messaging types based on `core::pipes` * [`std::sync`] - More exotic synchronization tools, including locks -* [`std::arc`] - The ARC type, for safely sharing immutable data +* [`std::arc`] - The ARC (atomic reference counted) type, for safely sharing + immutable data * [`std::par`] - Some basic tools for implementing parallel algorithms [`core::task`]: core/task.html @@ -74,11 +73,11 @@ concurrency at the moment. # Basics -The programming interface for creating and managing tasks is contained -in the `task` module of the `core` library, making it available to all -Rust code by default. At it's simplest, creating a task is a matter of -calling the `spawn` function, passing a closure to run in the new -task. +The programming interface for creating and managing tasks lives +in the `task` module of the `core` library, and is thus available to all +Rust code by default. At its simplest, creating a task is a matter of +calling the `spawn` function with a closure argument. `spawn` executes the +closure in the new task. ~~~~ # use io::println; @@ -97,17 +96,17 @@ do spawn { } ~~~~ -In Rust, there is nothing special about creating tasks - the language -itself doesn't know what a 'task' is. Instead, Rust provides in the -type system all the tools necessary to implement safe concurrency, -_owned types_ in particular, and leaves the dirty work up to the -core library. +In Rust, there is nothing special about creating tasks: a task is not a +concept that appears in the language semantics. Instead, Rust's type system +provides all the tools necessary to implement safe concurrency: particularly, +_owned types_. The language leaves the implementation details to the core +library. The `spawn` function has a very simple type signature: `fn spawn(f: ~fn())`. Because it accepts only owned closures, and owned closures -contained only owned data, `spawn` can safely move the entire closure +contain only owned data, `spawn` can safely move the entire closure and all its associated state into an entirely different task for -execution. Like any closure, the function passed to spawn may capture +execution. Like any closure, the function passed to `spawn` may capture an environment that it carries across tasks. ~~~ @@ -123,8 +122,8 @@ do spawn { } ~~~ -By default tasks will be multiplexed across the available cores, running -in parallel, thus on a multicore machine, running the following code +By default, the scheduler multiplexes tasks across the available cores, running +in parallel. Thus, on a multicore machine, running the following code should interleave the output in vaguely random order. ~~~ @@ -145,17 +144,16 @@ communicate with it. Recall that Rust does not have shared mutable state, so one task may not manipulate variables owned by another task. Instead we use *pipes*. -Pipes are simply a pair of endpoints, with one for sending messages -and another for receiving messages. Pipes are low-level communication -building-blocks and so come in a variety of forms, appropriate for -different use cases, but there are just a few varieties that are most -commonly used, which we will cover presently. +A pipe is simply a pair of endpoints: one for sending messages and another for +receiving messages. Pipes are low-level communication building-blocks and so +come in a variety of forms, each one appropriate for a different use case. In +what follows, we cover the most commonly used varieties. The simplest way to create a pipe is to use the `pipes::stream` -function to create a `(Chan, Port)` pair. In Rust parlance a 'channel' -is a sending endpoint of a pipe, and a 'port' is the receiving -endpoint. Consider the following example of performing two calculations -concurrently. +function to create a `(Chan, Port)` pair. In Rust parlance, a *channel* +is a sending endpoint of a pipe, and a *port* is the receiving +endpoint. Consider the following example of calculating two results +concurrently: ~~~~ use task::spawn; @@ -174,17 +172,17 @@ let result = port.recv(); # fn some_other_expensive_computation() {} ~~~~ -Let's examine this example in detail. The `let` statement first creates a -stream for sending and receiving integers (recall that `let` can be -used for destructuring patterns, in this case separating a tuple into -its component parts). +Let's examine this example in detail. First, the `let` statement creates a +stream for sending and receiving integers (the left-hand side of the `let`, +`(chan, port)`, is an example of a *destructuring let*: the pattern separates +a tuple into its component parts). ~~~~ # use pipes::{stream, Chan, Port}; let (chan, port): (Chan, Port) = stream(); ~~~~ -The channel will be used by the child task to send data to the parent task, +The child task will use the channel to send data to the parent task, which will wait to receive the data on the port. The next statement spawns the child task. @@ -200,14 +198,14 @@ do spawn { } ~~~~ -Notice that `chan` was transferred to the child task implicitly by -capturing it in the task closure. Both `Chan` and `Port` are sendable -types and may be captured into tasks or otherwise transferred between -them. In the example, the child task performs an expensive computation -then sends the result over the captured channel. +Notice that the creation of the task closure transfers `chan` to the child +task implicitly: the closure captures `chan` in its environment. Both `Chan` +and `Port` are sendable types and may be captured into tasks or otherwise +transferred between them. In the example, the child task runs an expensive +computation, then sends the result over the captured channel. -Finally, the parent continues by performing some other expensive -computation and then waiting for the child's result to arrive on the +Finally, the parent continues with some other expensive +computation, then waits for the child's result to arrive on the port: ~~~~ @@ -219,12 +217,11 @@ some_other_expensive_computation(); let result = port.recv(); ~~~~ -The `Port` and `Chan` pair created by `stream` enable efficient -communication between a single sender and a single receiver, but -multiple senders cannot use a single `Chan`, nor can multiple -receivers use a single `Port`. What if our example needed to perform -multiple computations across a number of tasks? The following cannot -be written: +The `Port` and `Chan` pair created by `stream` enables efficient communication +between a single sender and a single receiver, but multiple senders cannot use +a single `Chan`, and multiple receivers cannot use a single `Port`. What if our +example needed to computer multiple results across a number of tasks? The +following program is ill-typed: ~~~ {.xfail-test} # use task::{spawn}; @@ -265,18 +262,18 @@ let result = port.recv() + port.recv() + port.recv(); # fn some_expensive_computation(_i: uint) -> int { 42 } ~~~ -Here we transfer ownership of the channel into a new `SharedChan` -value. Like `Chan`, `SharedChan` is a non-copyable, owned type -(sometimes also referred to as an 'affine' or 'linear' type). Unlike -`Chan` though, `SharedChan` may be duplicated with the `clone()` -method. A cloned `SharedChan` produces a new handle to the same -channel, allowing multiple tasks to send data to a single port. -Between `spawn`, `stream` and `SharedChan` we have enough tools -to implement many useful concurrency patterns. +Here we transfer ownership of the channel into a new `SharedChan` value. Like +`Chan`, `SharedChan` is a non-copyable, owned type (sometimes also referred to +as an *affine* or *linear* type). Unlike with `Chan`, though, the programmer +may duplicate a `SharedChan`, with the `clone()` method. A cloned +`SharedChan` produces a new handle to the same channel, allowing multiple +tasks to send data to a single port. Between `spawn`, `stream` and +`SharedChan`, we have enough tools to implement many useful concurrency +patterns. Note that the above `SharedChan` example is somewhat contrived since you could also simply use three `stream` pairs, but it serves to -illustrate the point. For reference, written with multiple streams it +illustrate the point. For reference, written with multiple streams, it might look like the example below. ~~~ @@ -299,15 +296,17 @@ let result = ports.foldl(0, |accum, port| *accum + port.recv() ); # Handling task failure -Rust has a built-in mechanism for raising exceptions, written `fail` -(or `fail ~"reason"`, or sometimes `assert expr`), and it causes the -task to unwind its stack, running destructors and freeing memory along -the way, and then exit itself. Unlike C++, exceptions in Rust are -unrecoverable within a single task - once a task fails there is no way -to "catch" the exception. +Rust has a built-in mechanism for raising exceptions. The `fail` construct +(which can also be written with an error string as an argument: `fail +~reason`) and the `assert` construct (which effectively calls `fail` if a +boolean expression is false) are both ways to raise exceptions. When a task +raises an exception the task unwinds its stack---running destructors and +freeing memory along the way---and then exits. Unlike exceptions in C++, +exceptions in Rust are unrecoverable within a single task: once a task fails, +there is no way to "catch" the exception. -All tasks are, by default, _linked_ to each other, meaning their fate -is intertwined, and if one fails so do all of them. +All tasks are, by default, _linked_ to each other. That means that the fates +of all tasks are intertwined: if one fails, so do all the others. ~~~ # use task::spawn; @@ -321,11 +320,15 @@ do_some_work(); # }; ~~~ -While it isn't possible for a task to recover from failure, -tasks may be notified when _other_ tasks fail. The simplest way -of handling task failure is with the `try` function, which is -similar to spawn, but immediately blocks waiting for the child -task to finish. +While it isn't possible for a task to recover from failure, tasks may notify +each other of failure. The simplest way of handling task failure is with the +`try` function, which is similar to `spawn`, but immediately blocks waiting +for the child task to finish. `try` returns a value of type `Result`. `Result` is an `enum` type with two variants: `Ok` and `Err`. In this +case, because the type arguments to `Result` are `int` and `()`, callers can +pattern-match on a result to check whether it's an `Ok` result with an `int` +field (representing a successful result) or an `Err` result (representing +termination with an error). ~~~ # fn some_condition() -> bool { false } @@ -349,8 +352,8 @@ an `Error` result. [`Result`]: core/result.html > ***Note:*** A failed task does not currently produce a useful error -> value (all error results from `try` are equal to `Err(())`). In the -> future it may be possible for tasks to intercept the value passed to +> value (`try` always returns `Err(())`). In the +> future, it may be possible for tasks to intercept the value passed to > `fail`. TODO: Need discussion of `future_result` in order to make failure @@ -362,11 +365,11 @@ it trips, indicates an unrecoverable logic error); in other cases you might want to contain the failure at a certain boundary (perhaps a small piece of input from the outside world, which you happen to be processing in parallel, is malformed and its processing task can't -proceed). Hence the need for different _linked failure modes_. +proceed). Hence, you will need different _linked failure modes_. ## Failure modes -By default, task failure is _bidirectionally linked_, which means if +By default, task failure is _bidirectionally linked_, which means that if either task dies, it kills the other one. ~~~ @@ -382,8 +385,8 @@ sleep_forever(); // Will get woken up by force, then fail # }; ~~~ -If you want parent tasks to kill their children, but not for a child -task's failure to kill the parent, you can call +If you want parent tasks to be able to kill their children, but do not want a +parent to die automatically if one of its child task dies, you can call `task::spawn_supervised` for _unidirectionally linked_ failure. The function `task::try`, which we saw previously, uses `spawn_supervised` internally, with additional logic to wait for the child task to finish @@ -411,7 +414,7 @@ do try { // Unidirectionally linked Supervised failure is useful in any situation where one task manages multiple fallible child tasks, and the parent task can recover -if any child files. On the other hand, if the _parent_ (supervisor) fails +if any child fails. On the other hand, if the _parent_ (supervisor) fails, then there is nothing the children can do to recover, so they should also fail. @@ -456,11 +459,11 @@ fail; A very common thing to do is to spawn a child task where the parent and child both need to exchange messages with each other. The function `std::comm::DuplexStream()` supports this pattern. We'll -look briefly at how it is used. +look briefly at how to use it. To see how `spawn_conversation()` works, we will create a child task -that receives `uint` messages, converts them to a string, and sends -the string in response. The child terminates when `0` is received. +that repeatedly receives a `uint` message, converts it to a string, and sends +the string in response. The child terminates when it receives `0`. Here is the function that implements the child task: ~~~~ @@ -470,8 +473,8 @@ fn stringifier(channel: &DuplexStream<~str, uint>) { let mut value: uint; loop { value = channel.recv(); - channel.send(uint::to_str(value, 10u)); - if value == 0u { break; } + channel.send(uint::to_str(value, 10)); + if value == 0 { break; } } } ~~~~ @@ -481,7 +484,7 @@ receiving. The `stringifier` function takes a `DuplexStream` that can send strings (the first type parameter) and receive `uint` messages (the second type parameter). The body itself simply loops, reading from the channel and then sending its response back. The actual -response itself is simply the strified version of the received value, +response itself is simply the stringified version of the received value, `uint::to_str(value)`. Here is the code for the parent task: @@ -506,11 +509,11 @@ do spawn || { stringifier(&to_child); }; -from_child.send(22u); +from_child.send(22); assert from_child.recv() == ~"22"; -from_child.send(23u); -from_child.send(0u); +from_child.send(23); +from_child.send(0); assert from_child.recv() == ~"23"; assert from_child.recv() == ~"0"; @@ -518,6 +521,8 @@ assert from_child.recv() == ~"0"; # } ~~~~ -The parent task first calls `DuplexStream` to create a pair of bidirectional endpoints. It then uses `task::spawn` to create the child task, which captures one end of the communication channel. As a result, both parent -and child can send and receive data to and from the other. +The parent task first calls `DuplexStream` to create a pair of bidirectional +endpoints. It then uses `task::spawn` to create the child task, which captures +one end of the communication channel. As a result, both parent and child can +send and receive data to and from the other. From cd6f24f9d14ac90d167386a56e7a6ac1f0318195 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 9 Oct 2012 16:46:16 -0700 Subject: [PATCH 041/292] Copyedit FFI tutorial --- doc/tutorial-ffi.md | 129 ++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 65 deletions(-) diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md index 463bd4746fee..771384f41d83 100644 --- a/doc/tutorial-ffi.md +++ b/doc/tutorial-ffi.md @@ -2,17 +2,15 @@ # Introduction -One of Rust's aims, as a system programming language, is to +Because Rust is a systems programming language, one of its goals is to interoperate well with C code. -We'll start with an example. It's a bit bigger than usual, and -contains a number of new concepts. We'll go over it one piece at a -time. - -This is a program that uses OpenSSL's `SHA1` function to compute the -hash of its first command-line argument, which it then converts to a -hexadecimal string and prints to standard output. If you have the -OpenSSL libraries installed, it should 'just work'. +We'll start with an example, which is a bit bigger than usual. We'll +go over it one piece at a time. This is a program that uses OpenSSL's +`SHA1` function to compute the hash of its first command-line +argument, which it then converts to a hexadecimal string and prints to +standard output. If you have the OpenSSL libraries installed, it +should compile and run without any extra effort. ~~~~ {.xfail-test} extern mod std; @@ -32,7 +30,7 @@ fn sha1(data: ~str) -> ~str unsafe { let bytes = str::to_bytes(data); let hash = crypto::SHA1(vec::raw::to_ptr(bytes), vec::len(bytes) as c_uint, ptr::null()); - return as_hex(vec::raw::from_buf(hash, 20u)); + return as_hex(vec::raw::from_buf(hash, 20)); } fn main(args: ~[~str]) { @@ -42,26 +40,27 @@ fn main(args: ~[~str]) { # Foreign modules -Before we can call `SHA1`, we have to declare it. That is what this -part of the program is responsible for: +Before we can call the `SHA1` function defined in the OpenSSL library, we have +to declare it. That is what this part of the program does: ~~~~ {.xfail-test} extern mod crypto { - fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8; -} + fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8; } ~~~~ -An `extern` module declaration containing function signatures introduces -the functions listed as _foreign functions_, that are implemented in some -other language (usually C) and accessed through Rust's foreign function -interface (FFI). An extern module like this is called a foreign module, and -implicitly tells the compiler to link with a library with the same name as -the module, and that it will find the foreign functions in that library. +An `extern` module declaration containing function signatures introduces the +functions listed as _foreign functions_. Foreign functions differ from regular +Rust functions in that they are implemented in some other language (usually C) +and called through Rust's foreign function interface (FFI). An extern module +like this is called a foreign module, and implicitly tells the compiler to +link with a library that contains the listed foreign functions, and has the +same name as the module. -In this case, it'll change the name `crypto` to a shared library name -in a platform-specific way (`libcrypto.so` on Linux, for example), and -link that in. If you want the module to have a different name from the -actual library, you can use the `"link_name"` attribute, like: +In this case, the Rust compiler changes the name `crypto` to a shared library +name in a platform-specific way (`libcrypto.so` on Linux, for example), +searches for the shared library with that name, and links the library into the +program. If you want the module to have a different name from the actual +library, you can use the `"link_name"` attribute, like: ~~~~ {.xfail-test} #[link_name = "crypto"] @@ -72,11 +71,11 @@ extern mod something { # Foreign calling conventions -Most foreign code will be C code, which usually uses the `cdecl` calling +Most foreign code is C code, which usually uses the `cdecl` calling convention, so that is what Rust uses by default when calling foreign functions. Some foreign functions, most notably the Windows API, use other -calling conventions, so Rust provides a way to hint to the compiler which -is expected by using the `"abi"` attribute: +calling conventions. Rust provides the `"abi"` attribute as a way to hint to +the compiler which calling convention to use: ~~~~ #[cfg(target_os = "win32")] @@ -86,14 +85,14 @@ extern mod kernel32 { } ~~~~ -The `"abi"` attribute applies to a foreign module (it can not be applied +The `"abi"` attribute applies to a foreign module (it cannot be applied to a single function within a module), and must be either `"cdecl"` -or `"stdcall"`. Other conventions may be defined in the future. +or `"stdcall"`. We may extend the compiler in the future to support other +calling conventions. # Unsafe pointers -The foreign `SHA1` function is declared to take three arguments, and -return a pointer. +The foreign `SHA1` function takes three arguments, and returns a pointer. ~~~~ {.xfail-test} # extern mod crypto { @@ -104,21 +103,20 @@ fn SHA1(src: *u8, sz: libc::c_uint, out: *u8) -> *u8; When declaring the argument types to a foreign function, the Rust compiler has no way to check whether your declaration is correct, so you have to be careful. If you get the number or types of the -arguments wrong, you're likely to get a segmentation fault. Or, +arguments wrong, you're likely to cause a segmentation fault. Or, probably even worse, your code will work on one platform, but break on another. -In this case, `SHA1` is defined as taking two `unsigned char*` -arguments and one `unsigned long`. The rust equivalents are `*u8` +In this case, we declare that `SHA1` takes two `unsigned char*` +arguments and one `unsigned long`. The Rust equivalents are `*u8` unsafe pointers and an `uint` (which, like `unsigned long`, is a machine-word-sized type). -Unsafe pointers can be created through various functions in the -standard lib, usually with `unsafe` somewhere in their name. You can -dereference an unsafe pointer with `*` operator, but use -caution—unlike Rust's other pointer types, unsafe pointers are -completely unmanaged, so they might point at invalid memory, or be -null pointers. +The standard library provides various functions to create unsafe pointers, +such as those in `core::cast`. Most of these functions have `unsafe` in their +name. You can dereference an unsafe pointer with the `*` operator, but use +caution: unlike Rust's other pointer types, unsafe pointers are completely +unmanaged, so they might point at invalid memory, or be null pointers. # Unsafe blocks @@ -134,12 +132,12 @@ fn sha1(data: ~str) -> ~str { let bytes = str::to_bytes(data); let hash = crypto::SHA1(vec::raw::to_ptr(bytes), vec::len(bytes), ptr::null()); - return as_hex(vec::raw::from_buf(hash, 20u)); + return as_hex(vec::raw::from_buf(hash, 20)); } } ~~~~ -Firstly, what does the `unsafe` keyword at the top of the function +First, what does the `unsafe` keyword at the top of the function mean? `unsafe` is a block modifier—it declares the block following it to be known to be unsafe. @@ -158,8 +156,8 @@ advertise it to the world. An unsafe function is written like this: unsafe fn kaboom() { ~"I'm harmless!"; } ~~~~ -This function can only be called from an unsafe block or another -unsafe function. +This function can only be called from an `unsafe` block or another +`unsafe` function. # Pointer fiddling @@ -179,35 +177,36 @@ Let's look at our `sha1` function again. let bytes = str::to_bytes(data); let hash = crypto::SHA1(vec::raw::to_ptr(bytes), vec::len(bytes), ptr::null()); -return as_hex(vec::raw::from_buf(hash, 20u)); +return as_hex(vec::raw::from_buf(hash, 20)); # } # } ~~~~ -The `str::to_bytes` function is perfectly safe: it converts a string to -a `[u8]`. This byte array is then fed to `vec::raw::to_ptr`, which +The `str::to_bytes` function is perfectly safe: it converts a string to a +`~[u8]`. The program then feeds this byte array to `vec::raw::to_ptr`, which returns an unsafe pointer to its contents. -This pointer will become invalid as soon as the vector it points into -is cleaned up, so you should be very careful how you use it. In this -case, the local variable `bytes` outlives the pointer, so we're good. +This pointer will become invalid at the end of the scope in which the vector +it points to (`bytes`) is valid, so you should be very careful how you use +it. In this case, the local variable `bytes` outlives the pointer, so we're +good. Passing a null pointer as the third argument to `SHA1` makes it use a static buffer, and thus save us the effort of allocating memory -ourselves. `ptr::null` is a generic function that will return an -unsafe null pointer of the correct type (Rust generics are awesome -like that—they can take the right form depending on the type that they -are expected to return). +ourselves. `ptr::null` is a generic function that, in this case, returns an +unsafe null pointer of type `*u8`. (Rust generics are awesome +like that: they can take the right form depending on the type that they +are expected to return.) -Finally, `vec::raw::from_buf` builds up a new `[u8]` from the -unsafe pointer that was returned by `SHA1`. SHA1 digests are always -twenty bytes long, so we can pass `20u` for the length of the new +Finally, `vec::raw::from_buf` builds up a new `~[u8]` from the +unsafe pointer that `SHA1` returned. SHA1 digests are always +twenty bytes long, so we can pass `20` for the length of the new vector. # Passing structures C functions often take pointers to structs as arguments. Since Rust -structs are binary-compatible with C structs, Rust programs can call +`struct`s are binary-compatible with C structs, Rust programs can call such functions directly. This program uses the POSIX function `gettimeofday` to get a @@ -241,12 +240,12 @@ fn unix_time_in_microseconds() -> u64 unsafe { The `#[nolink]` attribute indicates that there's no foreign library to link in. The standard C library is already linked with Rust programs. -A `timeval`, in C, is a struct with two 32-bit integers. Thus, we -define a struct type with the same contents, and declare -`gettimeofday` to take a pointer to such a struct. +In C, a `timeval` is a struct with two 32-bit integer fields. Thus, we +define a `struct` type with the same contents, and declare +`gettimeofday` to take a pointer to such a `struct`. -The second argument to `gettimeofday` (the time zone) is not used by -this program, so it simply declares it to be a pointer to the nil -type. Since all null pointers have the same representation regardless of -their referent type, this is safe. +This program does not use the second argument to `gettimeofday` (the time + zone), so the `extern mod` declaration for it simply declares this argument + to be a pointer to the unit type (written `()`). Since all null pointers have + the same representation regardless of their referent type, this is safe. From c765c59ab19f7dcb2f9c5e90d5ea4e724df33904 Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Tue, 9 Oct 2012 19:59:17 -0400 Subject: [PATCH 042/292] core::str - making StrSlice trait functions pure --- src/libcore/str.rs | 108 +++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d743f0c7f3be..1256e5b5617c 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1361,7 +1361,7 @@ pub pure fn is_whitespace(s: &str) -> bool { * * Alphanumeric characters are determined by `char::is_alphanumeric` */ -fn is_alphanumeric(s: &str) -> bool { +pure fn is_alphanumeric(s: &str) -> bool { return all(s, char::is_alphanumeric); } @@ -2030,22 +2030,22 @@ pub mod raw { } pub trait UniqueStr { - fn trim() -> self; - fn trim_left() -> self; - fn trim_right() -> self; + pure fn trim() -> self; + pure fn trim_left() -> self; + pure fn trim_right() -> self; } /// Extension methods for strings impl ~str: UniqueStr { /// Returns a string with leading and trailing whitespace removed #[inline] - fn trim() -> ~str { trim(self) } + pure fn trim() -> ~str { trim(self) } /// Returns a string with leading whitespace removed #[inline] - fn trim_left() -> ~str { trim_left(self) } + pure fn trim_left() -> ~str { trim_left(self) } /// Returns a string with trailing whitespace removed #[inline] - fn trim_right() -> ~str { trim_right(self) } + pure fn trim_right() -> ~str { trim_right(self) } } #[cfg(notest)] @@ -2062,33 +2062,33 @@ pub mod traits { pub mod traits {} pub trait StrSlice { - fn all(it: fn(char) -> bool) -> bool; - fn any(it: fn(char) -> bool) -> bool; - fn contains(needle: &a/str) -> bool; - fn contains_char(needle: char) -> bool; - fn each(it: fn(u8) -> bool); - fn eachi(it: fn(uint, u8) -> bool); - fn each_char(it: fn(char) -> bool); - fn each_chari(it: fn(uint, char) -> bool); - fn ends_with(needle: &str) -> bool; - fn is_empty() -> bool; - fn is_not_empty() -> bool; - fn is_whitespace() -> bool; - fn is_alphanumeric() -> bool; + pure fn all(it: fn(char) -> bool) -> bool; + pure fn any(it: fn(char) -> bool) -> bool; + pure fn contains(needle: &a/str) -> bool; + pure fn contains_char(needle: char) -> bool; + pure fn each(it: fn(u8) -> bool); + pure fn eachi(it: fn(uint, u8) -> bool); + pure fn each_char(it: fn(char) -> bool); + pure fn each_chari(it: fn(uint, char) -> bool); + pure fn ends_with(needle: &str) -> bool; + pure fn is_empty() -> bool; + pure fn is_not_empty() -> bool; + pure fn is_whitespace() -> bool; + pure fn is_alphanumeric() -> bool; pure fn len() -> uint; pure fn slice(begin: uint, end: uint) -> ~str; - fn split(sepfn: fn(char) -> bool) -> ~[~str]; - fn split_char(sep: char) -> ~[~str]; - fn split_str(sep: &a/str) -> ~[~str]; - fn starts_with(needle: &a/str) -> bool; - fn substr(begin: uint, n: uint) -> ~str; + pure fn split(sepfn: fn(char) -> bool) -> ~[~str]; + pure fn split_char(sep: char) -> ~[~str]; + pure fn split_str(sep: &a/str) -> ~[~str]; + pure fn starts_with(needle: &a/str) -> bool; + pure fn substr(begin: uint, n: uint) -> ~str; pure fn to_lower() -> ~str; pure fn to_upper() -> ~str; - fn escape_default() -> ~str; - fn escape_unicode() -> ~str; - fn trim() -> ~str; - fn trim_left() -> ~str; - fn trim_right() -> ~str; + pure fn escape_default() -> ~str; + pure fn escape_unicode() -> ~str; + pure fn trim() -> ~str; + pure fn trim_left() -> ~str; + pure fn trim_right() -> ~str; pure fn to_unique() -> ~str; pure fn char_at(i: uint) -> char; } @@ -2100,54 +2100,56 @@ impl &str: StrSlice { * contains no characters */ #[inline] - fn all(it: fn(char) -> bool) -> bool { all(self, it) } + pure fn all(it: fn(char) -> bool) -> bool { all(self, it) } /** * Return true if a predicate matches any character (and false if it * matches none or there are no characters) */ #[inline] - fn any(it: fn(char) -> bool) -> bool { any(self, it) } + pure fn any(it: fn(char) -> bool) -> bool { any(self, it) } /// Returns true if one string contains another #[inline] - fn contains(needle: &a/str) -> bool { contains(self, needle) } + pure fn contains(needle: &a/str) -> bool { contains(self, needle) } /// Returns true if a string contains a char #[inline] - fn contains_char(needle: char) -> bool { contains_char(self, needle) } + pure fn contains_char(needle: char) -> bool { + contains_char(self, needle) + } /// Iterate over the bytes in a string #[inline] - fn each(it: fn(u8) -> bool) { each(self, it) } + pure fn each(it: fn(u8) -> bool) { each(self, it) } /// Iterate over the bytes in a string, with indices #[inline] - fn eachi(it: fn(uint, u8) -> bool) { eachi(self, it) } + pure fn eachi(it: fn(uint, u8) -> bool) { eachi(self, it) } /// Iterate over the chars in a string #[inline] - fn each_char(it: fn(char) -> bool) { each_char(self, it) } + pure fn each_char(it: fn(char) -> bool) { each_char(self, it) } /// Iterate over the chars in a string, with indices #[inline] - fn each_chari(it: fn(uint, char) -> bool) { each_chari(self, it) } + pure fn each_chari(it: fn(uint, char) -> bool) { each_chari(self, it) } /// Returns true if one string ends with another #[inline] - fn ends_with(needle: &str) -> bool { ends_with(self, needle) } + pure fn ends_with(needle: &str) -> bool { ends_with(self, needle) } /// Returns true if the string has length 0 #[inline] - fn is_empty() -> bool { is_empty(self) } + pure fn is_empty() -> bool { is_empty(self) } /// Returns true if the string has length greater than 0 #[inline] - fn is_not_empty() -> bool { is_not_empty(self) } + pure fn is_not_empty() -> bool { is_not_empty(self) } /** * Returns true if the string contains only whitespace * * Whitespace characters are determined by `char::is_whitespace` */ #[inline] - fn is_whitespace() -> bool { is_whitespace(self) } + pure fn is_whitespace() -> bool { is_whitespace(self) } /** * Returns true if the string contains only alphanumerics * * Alphanumeric characters are determined by `char::is_alphanumeric` */ #[inline] - fn is_alphanumeric() -> bool { is_alphanumeric(self) } + pure fn is_alphanumeric() -> bool { is_alphanumeric(self) } #[inline] /// Returns the size in bytes not counting the null terminator pure fn len() -> uint { len(self) } @@ -2162,21 +2164,21 @@ impl &str: StrSlice { pure fn slice(begin: uint, end: uint) -> ~str { slice(self, begin, end) } /// Splits a string into substrings using a character function #[inline] - fn split(sepfn: fn(char) -> bool) -> ~[~str] { split(self, sepfn) } + pure fn split(sepfn: fn(char) -> bool) -> ~[~str] { split(self, sepfn) } /** * Splits a string into substrings at each occurrence of a given character */ #[inline] - fn split_char(sep: char) -> ~[~str] { split_char(self, sep) } + pure fn split_char(sep: char) -> ~[~str] { split_char(self, sep) } /** * Splits a string into a vector of the substrings separated by a given * string */ #[inline] - fn split_str(sep: &a/str) -> ~[~str] { split_str(self, sep) } + pure fn split_str(sep: &a/str) -> ~[~str] { split_str(self, sep) } /// Returns true if one string starts with another #[inline] - fn starts_with(needle: &a/str) -> bool { starts_with(self, needle) } + pure fn starts_with(needle: &a/str) -> bool { starts_with(self, needle) } /** * Take a substring of another. * @@ -2184,7 +2186,7 @@ impl &str: StrSlice { * `begin`. */ #[inline] - fn substr(begin: uint, n: uint) -> ~str { substr(self, begin, n) } + pure fn substr(begin: uint, n: uint) -> ~str { substr(self, begin, n) } /// Convert a string to lowercase #[inline] pure fn to_lower() -> ~str { to_lower(self) } @@ -2193,20 +2195,20 @@ impl &str: StrSlice { pure fn to_upper() -> ~str { to_upper(self) } /// Escape each char in `s` with char::escape_default. #[inline] - fn escape_default() -> ~str { escape_default(self) } + pure fn escape_default() -> ~str { escape_default(self) } /// Escape each char in `s` with char::escape_unicode. #[inline] - fn escape_unicode() -> ~str { escape_unicode(self) } + pure fn escape_unicode() -> ~str { escape_unicode(self) } /// Returns a string with leading and trailing whitespace removed #[inline] - fn trim() -> ~str { trim(self) } + pure fn trim() -> ~str { trim(self) } /// Returns a string with leading whitespace removed #[inline] - fn trim_left() -> ~str { trim_left(self) } + pure fn trim_left() -> ~str { trim_left(self) } /// Returns a string with trailing whitespace removed #[inline] - fn trim_right() -> ~str { trim_right(self) } + pure fn trim_right() -> ~str { trim_right(self) } #[inline] pure fn to_unique() -> ~str { self.slice(0, self.len()) } From a46db484abcdd517c0116301c77364e8e1c373af Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 9 Oct 2012 17:12:34 -0700 Subject: [PATCH 043/292] Copyedit first two sections of borrowed pointer tutorial --- doc/tutorial-borrowed-ptr.md | 92 ++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md index 8b264a9d609d..0ca6045b79f7 100644 --- a/doc/tutorial-borrowed-ptr.md +++ b/doc/tutorial-borrowed-ptr.md @@ -2,32 +2,32 @@ # Introduction -Borrowed pointers are one of the more flexible and powerful tools -available in Rust. A borrowed pointer can be used to point anywhere: -into the managed and exchange heaps, into the stack, and even into the -interior of another data structure. With regard to flexibility, it is -comparable to a C pointer or C++ reference. However, unlike C and C++, -the Rust compiler includes special checks that ensure that borrowed -pointers are being used safely. Another advantage of borrowed pointers -is that they are invisible to the garbage collector, so working with -borrowed pointers helps keep things efficient. +Borrowed pointers are one of the more flexible and powerful tools available in +Rust. A borrowed pointer can point anywhere: into the managed or exchange +heap, into the stack, and even into the interior of another data structure. A +borrowed pointer is as flexible as a C pointer or C++ reference. However, +unlike C and C++ compilers, the Rust compiler includes special static checks +that ensure that programs use borrowed pointers safely. Another advantage of +borrowed pointers is that they are invisible to the garbage collector, so +working with borrowed pointers helps reduce the overhead of automatic memory +management. -Despite the fact that they are completely safe, at runtime, a borrowed -pointer is “just a pointer”. They introduce zero overhead. All safety -checks are done at compilation time. +Despite their complete safety, a borrowed pointer's representation at runtime +is the same as that of an ordinary pointer in a C program. They introduce zero +overhead. The compiler does all safety checks at compile time. Although borrowed pointers have rather elaborate theoretical underpinnings (region pointers), the core concepts will be familiar to -anyone who worked with C or C++. Therefore, the best way to explain +anyone who has worked with C or C++. Therefore, the best way to explain how they are used—and their limitations—is probably just to work through several examples. # By example -Borrowed pointers are called borrowed because they are only valid for -a limit duration. Borrowed pointers never claim any kind of ownership -over the data that they point at: instead, they are used for cases -where you like to make use of data for a short time. +Borrowed pointers are called *borrowed* because they are only valid for +a limited duration. Borrowed pointers never claim any kind of ownership +over the data that they point to: instead, they are used for cases +where you would like to use data for a short time. As an example, consider a simple struct type `Point`: @@ -35,7 +35,7 @@ As an example, consider a simple struct type `Point`: struct Point {x: float, y: float} ~~~ -We can use this simple definition to allocate points in many ways. For +We can use this simple definition to allocate points in many different ways. For example, in this code, each of these three local variables contains a point, but allocated in a different place: @@ -46,17 +46,17 @@ let shared_box : @Point = @Point {x: 5.0, y: 1.0}; let unique_box : ~Point = ~Point {x: 7.0, y: 9.0}; ~~~ -Suppose we wanted to write a procedure that computed the distance -between any two points, no matter where they were stored. For example, -we might like to compute the distance between `on_the_stack` and -`shared_box`, or between `shared_box` and `unique_box`. One option is -to define a function that takes two arguments of type point—that is, -it takes the points by value. But this will cause the points to be -copied when we call the function. For points, this is probably not so -bad, but often copies are expensive or, worse, if there are mutable -fields, they can change the semantics of your program. So we’d like to -define a function that takes the points by pointer. We can use -borrowed pointers to do this: +Suppose we wanted to write a procedure that computed the distance between any +two points, no matter where they were stored. For example, we might like to +compute the distance between `on_the_stack` and `shared_box`, or between +`shared_box` and `unique_box`. One option is to define a function that takes +two arguments of type `Point`—that is, it takes the points by value. But we +define it this way, calling the function will cause the points to be +copied. For points, this is probably not so bad, but often copies are +expensive. Worse, if the data type contains mutable fields, copying can change +the semantics of your program in unexpected ways. So we'd like to define a +function that takes the points by pointer. We can use borrowed pointers to do +this: ~~~ # struct Point {x: float, y: float} @@ -80,28 +80,28 @@ compute_distance(&on_the_stack, shared_box); compute_distance(shared_box, unique_box); ~~~ -Here the `&` operator is used to take the address of the variable +Here, the `&` operator takes the address of the variable `on_the_stack`; this is because `on_the_stack` has the type `Point` (that is, a struct value) and we have to take its address to get a value. We also call this _borrowing_ the local variable -`on_the_stack`, because we are created an alias: that is, another -route to the same data. +`on_the_stack`, because we have created an alias: that is, another +name for the same data. -In the case of the boxes `shared_box` and `unique_box`, however, no -explicit action is necessary. The compiler will automatically convert -a box like `@Point` or `~Point` to a borrowed pointer like -`&Point`. This is another form of borrowing; in this case, the -contents of the shared/unique box is being lent out. +In contrast, we can pass the boxes `shared_box` and `unique_box` to +`compute_distance` directly. The compiler automatically converts a box like +`@Point` or `~Point` to a borrowed pointer like `&Point`. This is another form +of borrowing: in this case, the caller lends the contents of the shared or +unique box to the callee. -Whenever a value is borrowed, there are some limitations on what you -can do with the original. For example, if the contents of a variable -have been lent out, you cannot send that variable to another task, nor -will you be permitted to take actions that might cause the borrowed -value to be freed or to change its type (I’ll get into what kinds of -actions those are shortly). This rule should make intuitive sense: you -must wait for a borrowed value to be returned (that is, for the -borrowed pointer to go out of scope) before you can make full use of -it again. +Whenever a caller lends data to a callee, there are some limitations on what +the caller can do with the original. For example, if the contents of a +variable have been lent out, you cannot send that variable to another task. In +addition, the compiler will reject any code that might cause the borrowed +value to be freed or overwrite its component fields with values of different +types (I'll get into what kinds of actions those are shortly). This rule +should make intuitive sense: you must wait for a borrower to return the value +that you lent it (that is, wait for the borrowed pointer to go out of scope) +before you can make full use of it again. # Other uses for the & operator From e325d029d4c0a0102de0000963cad7282f9f9ddd Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 9 Oct 2012 16:33:03 -0700 Subject: [PATCH 044/292] Remove old serialization2 vestigial code --- src/libstd/ebml2.rs | 1 - src/libstd/prettyprint2.rs | 1 - src/libstd/serialization2.rs | 7 ------- src/libstd/std.rc | 3 --- src/rustc/metadata/csearch.rs | 4 ++-- 5 files changed, 2 insertions(+), 14 deletions(-) delete mode 100644 src/libstd/ebml2.rs delete mode 100644 src/libstd/prettyprint2.rs delete mode 100644 src/libstd/serialization2.rs diff --git a/src/libstd/ebml2.rs b/src/libstd/ebml2.rs deleted file mode 100644 index f5410233c921..000000000000 --- a/src/libstd/ebml2.rs +++ /dev/null @@ -1 +0,0 @@ -pub use ebml::*; diff --git a/src/libstd/prettyprint2.rs b/src/libstd/prettyprint2.rs deleted file mode 100644 index a3bf40ecf72f..000000000000 --- a/src/libstd/prettyprint2.rs +++ /dev/null @@ -1 +0,0 @@ -pub use prettyprint::*; diff --git a/src/libstd/serialization2.rs b/src/libstd/serialization2.rs deleted file mode 100644 index 9ea544778694..000000000000 --- a/src/libstd/serialization2.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Support code for serialization. - -/* -Core serialization interfaces. -*/ - -pub use serialization::*; diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 7fc3004bbcfa..88ef03aa5349 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -69,7 +69,6 @@ pub mod treemap; // And ... other stuff pub mod ebml; -pub mod ebml2; pub mod dbg; pub mod getopts; pub mod json; @@ -79,7 +78,6 @@ pub mod tempfile; pub mod term; pub mod time; pub mod prettyprint; -pub mod prettyprint2; pub mod arena; pub mod par; pub mod cmp; @@ -93,7 +91,6 @@ mod unicode; pub mod test; pub mod serialization; -pub mod serialization2; // Local Variables: // mode: rust; diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index 52813eb6b75d..5f5f938541f1 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -1,6 +1,6 @@ // Searching for information from the cstore -use std::ebml2; +use std::ebml; use syntax::ast; use syntax::ast_util; use syntax::ast_map; @@ -136,7 +136,7 @@ fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id, def: ast::def_id) -> ty::ty_param_bounds_and_ty { let cstore = tcx.cstore; let cdata = cstore::get_crate_data(cstore, class_id.crate); - let all_items = ebml2::get_doc(ebml2::Doc(cdata.data), tag_items); + let all_items = ebml::get_doc(ebml::Doc(cdata.data), tag_items); debug!("Looking up %?", class_id); let class_doc = expect(tcx.diag, decoder::maybe_find_item(class_id.node, all_items), From fe1165f5610a5c35ec94e3524200977fdf64ef0c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 9 Oct 2012 20:04:15 -0700 Subject: [PATCH 045/292] Tighten up language surrounding declarations, assignments, inits, lvals. --- doc/rust.md | 64 ++++++++++++++++++----------------------------------- 1 file changed, 22 insertions(+), 42 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 66552c29017f..7c859f90ebef 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1435,27 +1435,11 @@ let_decl : "let" pat [':' type ] ? [ init ] ? ';' ; init : [ '=' | '<-' ] expr ; ~~~~~~~~ - -A _slot declaration_ has one of two forms: - -* `let` `pattern` `optional-init`; -* `let` `pattern` : `type` `optional-init`; - -Where `type` is a type expression, `pattern` is an irrefutable pattern (often -just the name of a single slot), and `optional-init` is an optional -initializer. If present, the initializer consists of either an assignment -operator (`=`) or move operator (`<-`), followed by an expression. - -Both forms introduce a new slot into the enclosing block scope. The new slot -is visible from the point of declaration until the end of the enclosing block -scope. - -The former form, with no type annotation, causes the compiler to infer the -static type of the slot through unification with the types of values assigned -to the slot in the remaining code in the block scope. Inference only occurs on -frame-local variable, not argument slots. Function signatures must -always declare types for all argument slots. - +A _slot declaration_ introduces a new set of slots, given by a pattern. +The pattern may be followed by a type annotation, and/or an initializer expression. +When no type annotation is given, the compiler will infer the type, +or signal an error if insufficient type information is available for definite inference. +Any slots introduced by a slot declaration are visible from the point of declaration until the end of the enclosing block scope. ### Expression statements @@ -1487,7 +1471,8 @@ The evaluation of an expression depends both on its own category and the context Path, field and index expressions are lvalues. All other expressions are rvalues. -The left operand of an assignment expression and the operand of the borrow operator are lvalue contexts. +The left operand of an assignment, compound-assignment, or binary move expression is an lvalue context, +as is the single operand of a borrow, unary copy or move expression, and _both_ operands of a swap expression. All other expression contexts are rvalue contexts. When an lvalue is evaluated in an _lvalue context_, it denotes a memory location; @@ -1572,9 +1557,8 @@ myrecord.myfield; {a: 10, b: 20}.a; ~~~~~~~~ -A field access on a record is an _lval_ referring to the value of that -field. When the field is mutable, it can be -[assigned](#assignment-expressions) to. +A field access on a record is an [lvalue](#lvalues-rvalues-and-temporaries) referring to the value of that field. +When the field is mutable, it can be [assigned](#assignment-expressions) to. When the type of the expression to the left of the dot is a boxed record, it is automatically derferenced to make the field access @@ -1615,7 +1599,7 @@ idx_expr : expr '[' expr ']' [Vector](#vector-types)-typed expressions can be indexed by writing a square-bracket-enclosed expression (the index) after them. When the -vector is mutable, the resulting _lval_ can be assigned to. +vector 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 @@ -1641,7 +1625,7 @@ operators, before the expression they apply to. `*` : Dereference. When applied to a [box](#box-types) or [resource](#resources) type, it accesses the inner value. For - mutable boxes, the resulting _lval_ can be assigned to. For + mutable boxes, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to. For [enums](#enumerated-types) that have only a single variant, containing a single parameter, the dereference operator accesses this parameter. @@ -1762,11 +1746,11 @@ types. #### Binary move expressions -A _binary move expression_ consists of an *lval* followed by a left-pointing -arrow (`<-`) and an *rval* expression. +A _binary move expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) followed by a left-pointing +arrow (`<-`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression. -Evaluating a move expression causes, as a side effect, the *rval* to be -*moved* into the *lval*. If the *rval* was itself an *lval*, it must be a +Evaluating a move expression causes, as a side effect, the rvalue to be +*moved* into the lvalue. If the rvalue was itself an lvalue, it must be a local variable, as it will be de-initialized in the process. Evaluating a move expression does not change reference counts, nor does it @@ -1792,17 +1776,13 @@ y.z <- c; #### Swap expressions -A _swap expression_ consists of an *lval* followed by a bi-directional arrow -(`<->`) and another *lval* expression. +A _swap expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) followed by a bi-directional arrow (`<->`) and another [lvalue](#lvalues-rvalues-and-temporaries). -Evaluating a swap expression causes, as a side effect, the values held in the -left-hand-side and right-hand-side *lvals* to be exchanged indivisibly. +Evaluating a swap expression causes, as a side effect, the values held in the left-hand-side and right-hand-side [lvalues](#lvalues-rvalues-and-temporaries) to be exchanged indivisibly. -Evaluating a swap expression neither changes reference counts nor deeply -copies any unique structure pointed to by the moved -*rval*. Instead, the swap expression represents an indivisible *exchange of -ownership* between the right-hand-side and the left-hand-side of the -expression. No allocation or destruction is entailed. +Evaluating a swap expression neither changes reference counts nor deeply copies any unique structure pointed to by the moved [rvalue](#lvalues-rvalues-and-temporaries). +Instead, the swap expression represents an indivisible *exchange of ownership* between the right-hand-side and the left-hand-side of the expression. +No allocation or destruction is entailed. An example of three different swap expressions: @@ -1821,8 +1801,8 @@ y.z <-> b.c; #### Assignment expressions -An _assignment expression_ consists of an *lval* expression followed by an -equals sign (`=`) and an *rval* expression. +An _assignment expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) expression followed by an +equals sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression. Evaluating an assignment expression is equivalent to evaluating a [binary move expression](#binary-move-expressions) applied to a [unary copy From f016fd43f868cffa8759f18c4772a1423e48ccd1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 9 Oct 2012 20:05:10 -0700 Subject: [PATCH 046/292] Remove section on 'note' expressions, they won't exist. --- doc/rust.md | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 7c859f90ebef..f24371cb8d51 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2182,54 +2182,6 @@ the *failing* state, a task unwinds its stack, destroying all frames and freeing all resources until it reaches its entry frame, at which point it halts execution in the *dead* state. -### Note expressions - -~~~~~~~~{.ebnf .gram} -note_expr : "note" expr ; -~~~~~~~~ - -**Note: Note expressions are not yet supported by the compiler.** - -A `note` expression has no effect during normal execution. The purpose of a -`note` expression is to provide additional diagnostic information to the -logging subsystem during task failure. See [log -expressions](#log-expressions). Using `note` expressions, normal diagnostic -logging can be kept relatively sparse, while still providing verbose -diagnostic "back-traces" when a task fails. - -When a task is failing, control frames *unwind* from the innermost frame to -the outermost, and from the innermost lexical block within an unwinding frame -to the outermost. When unwinding a lexical block, the runtime processes all -the `note` expressions in the block sequentially, from the first expression of -the block to the last. During processing, a `note` expression has equivalent -meaning to a `log` expression: it causes the runtime to append the argument of -the `note` to the internal logging diagnostic buffer. - -An example of a `note` expression: - -~~~~{.xfail-test} -fn read_file_lines(path: ~str) -> ~[~str] { - note path; - let r: [~str]; - let f: file = open_read(path); - lines(f) |s| { - r += ~[s]; - } - return r; -} -~~~~ - -In this example, if the task fails while attempting to open or read a file, -the runtime will log the path name that was being read. If the function -completes normally, the runtime will not log the path. - -A value that is marked by a `note` expression is *not* copied aside -when control passes through the `note`. In other words, if a `note` -expression notes a particular `lval`, and code after the `note` -mutates that slot, and then a subsequent failure occurs, the *mutated* -value will be logged during unwinding, *not* the original value that was -denoted by the `lval` at the moment control passed through the `note` -expression. ### Return expressions From 6da09c3b437dad240218b91ea06c301982764152 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 9 Oct 2012 21:21:07 -0700 Subject: [PATCH 047/292] doc: Fix some inaccuracies in the tutorial. * Pointers can refer to stack objects as well as heap objects. * Non-managed types can be cyclic if an arena is used. --- doc/tutorial.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index d49fcf92cabe..dc88b2a8911a 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1054,7 +1054,7 @@ copied, not just a pointer. For small structs like `Point`, this is usually more efficient than allocating memory and going through a pointer. But for big structs, or those with mutable fields, it can be useful to have a single copy on -the heap, and refer to that through a pointer. +the stack or on the heap, and refer to that through a pointer. Rust supports several types of pointers. The safe pointer types are `@T` for managed boxes allocated on the local heap, `~T`, for @@ -1087,8 +1087,7 @@ let y = x; // Copy of a pointer to the same box ~~~~ Any type that contains managed boxes or other managed types is -considered _managed_. Managed types are the only types that can -construct cyclic data structures in Rust, such as doubly-linked lists. +considered _managed_. ~~~ // A linked list node From d9317a174e434d4c99fc1a37fd7dc0d2f5328d37 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 9 Oct 2012 21:39:18 -0700 Subject: [PATCH 048/292] doc: Tweak the wording of the memory model goals --- doc/tutorial.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index dc88b2a8911a..59117d339a1d 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -988,16 +988,17 @@ illuminate several of Rust's unique features as we encounter them. Rust has three competing goals that inform its view of memory: -* Memory safety: memory that is managed by and is accessible to the - Rust language must be guaranteed to be valid; under normal +* Memory safety: Memory that is managed by and is accessible to the + Rust language must be guaranteed to be valid. Under normal circumstances it must be impossible for Rust to trigger a - segmentation fault or leak memory -* Performance: high-performance low-level code must be able to employ - a number of allocation strategies; low-performance high-level code - must be able to employ a single, garbage-collection-based, heap - allocation strategy -* Concurrency: Rust must maintain memory safety guarantees, even for - code running in parallel + segmentation fault or leak memory. +* Performance: High-performance low-level code must be able to employ + a number of allocation strategies. Tracing garbage collection must be + optional and, if it is not desired, memory safety must not be compromised. + Less performance-critical, high-level code should be able to employ a single, + garbage-collection-based, heap allocation strategy. +* Concurrency: Rust code must be free of in-memory data races. (Note that other + types of races are still possible.) ## How performance considerations influence the memory model From 0d8f447d560d378adebfbad948427adfc2f5ae22 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 9 Oct 2012 21:45:08 -0700 Subject: [PATCH 049/292] Register snapshots. --- src/snapshots.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/snapshots.txt b/src/snapshots.txt index d00a037a0f12..05a4ec10c45d 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,11 @@ +S 2012-10-09 cd6f24f + macos-i386 7f2f2857eac33ff0792e4ea7a3ff91a09304fcab + macos-x86_64 bb3d191e2e31cb754223ab162281fd9727e63ea9 + freebsd-x86_64 a2b5e9dddfa8f21cc8a068b77a47ba5425bfdcc6 + linux-i386 7c13c04ed6593dc77db6b3b56f057213f567a32b + linux-x86_64 7860cdd4023e9d6bec892dc5a7144b286a7fd38e + winnt-i386 9e917c2f3d72f72042d5e9b60b45790740676e82 + S 2012-10-08 a477c5a macos-i386 c059c3d5bd113f7edec48a4c2128f4b6138c3db8 macos-x86_64 f121f4e2d831434f7825f72f3d328c11b13a522f From 25096a212a9ccaa0d181630af5971532c3472182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Br=C3=BCschweiler?= Date: Wed, 10 Oct 2012 22:40:17 +0200 Subject: [PATCH 050/292] rustc: fix size computation of structs for the FFI It didn't take alignment into account. Fixes #3656. --- src/rustc/middle/trans/foreign.rs | 7 ++++--- src/test/run-pass/issue-3656.rs | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/issue-3656.rs diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index 74dadd2cab49..4a87eb57cbe2 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -112,9 +112,10 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] { Float => 4, Double => 8, Struct => { - do vec::foldl(0, struct_tys(ty)) |s, t| { - s + ty_size(*t) - } + let size = do vec::foldl(0, struct_tys(ty)) |s, t| { + align(s, *t) + ty_size(*t) + }; + align(size, ty) } Array => { let len = llvm::LLVMGetArrayLength(ty) as uint; diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs new file mode 100644 index 000000000000..feb7ad1db7a8 --- /dev/null +++ b/src/test/run-pass/issue-3656.rs @@ -0,0 +1,20 @@ +// Issue #3656 +// Incorrect struct size computation in the FFI, because of not taking +// the alignment of elements into account. + +use libc::*; + +struct KEYGEN { + hash_algorithm: [c_uint]/2, + count: uint32_t, + salt: *c_void, + salt_size: uint32_t, +} + +extern { + // Bogus signature, just need to test if it compiles. + pub fn malloc(++data: KEYGEN); +} + +fn main() { +} From f4a6b84a65bf9c3b548e4e5d3f2aa2d9a8495085 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 13:56:08 -0700 Subject: [PATCH 051/292] Copyedit sections 3 and 4 of the borrowed pointer tutorial --- doc/tutorial-borrowed-ptr.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md index 0ca6045b79f7..712c0cba9b42 100644 --- a/doc/tutorial-borrowed-ptr.md +++ b/doc/tutorial-borrowed-ptr.md @@ -112,10 +112,10 @@ In the previous example, the value `on_the_stack` was defined like so: let on_the_stack: Point = Point {x: 3.0, y: 4.0}; ~~~ -This results in a by-value variable. As a consequence, we had to -explicitly take the address of `on_the_stack` to get a borrowed -pointer. Sometimes however it is more convenient to move the & -operator into the definition of `on_the_stack`: +This declaration means that code can only pass `Point` by value to other +functions. As a consequence, we had to explicitly take the address of +`on_the_stack` to get a borrowed pointer. Sometimes however it is more +convenient to move the & operator into the definition of `on_the_stack`: ~~~ # struct Point {x: float, y: float} @@ -123,7 +123,8 @@ let on_the_stack2: &Point = &Point {x: 3.0, y: 4.0}; ~~~ Applying `&` to an rvalue (non-assignable location) is just a convenient -shorthand for creating a temporary and taking its address: +shorthand for creating a temporary and taking its address. A more verbose +way to write the same code is: ~~~ # struct Point {x: float, y: float} @@ -134,7 +135,7 @@ let on_the_stack2 : &Point = &tmp; # Taking the address of fields As in C, the `&` operator is not limited to taking the address of -local variables. It can also be used to take the address of fields or +local variables. It can also take the address of fields or individual array elements. For example, consider this type definition for `rectangle`: @@ -144,7 +145,7 @@ struct Size {w: float, h: float} // as before struct Rectangle {origin: Point, size: Size} ~~~ -Now again I can define rectangles in a few different ways: +Now, as before, we can define rectangles in a few different ways: ~~~ # struct Point {x: float, y: float} @@ -158,8 +159,8 @@ let rect_unique = ~Rectangle {origin: Point {x: 5f, y: 6f}, size: Size {w: 3f, h: 4f}}; ~~~ -In each case I can use the `&` operator to extact out individual -subcomponents. For example, I could write: +In each case, we can extract out individual subcomponents with the `&` +operator. For example, I could write: ~~~ # struct Point {x: float, y: float} // as before @@ -173,7 +174,7 @@ compute_distance(&rect_stack.origin, &rect_managed.origin); ~~~ which would borrow the field `origin` from the rectangle on the stack -from the managed box and then compute the distance between them. +as well as from the managed box, and then compute the distance between them. # Borrowing managed boxes and rooting From e356959bb281bf09d2723fa89780243415c8eca1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 14:05:53 -0700 Subject: [PATCH 052/292] Attempt to fix the DSYM_GLOB issue again, differently. --- mk/platform.mk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mk/platform.mk b/mk/platform.mk index 43a943347a57..67eaa1b878b3 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -19,6 +19,10 @@ CFG_GCCISH_CFLAGS += -fno-omit-frame-pointer # embedded into the executable, so use a no-op command. CFG_DSYMUTIL := true +# Add a dSYM glob for all platforms, even though it will do nothing on +# non-Darwin platforms; omitting it causes a full -R copy of lib/ +CFG_LIB_DSYM_GLOB=lib$(1)-*.dylib.dSYM + ifneq ($(findstring freebsd,$(CFG_OSTYPE)),) CFG_LIB_NAME=lib$(1).so CFG_LIB_GLOB=lib$(1)-*.so @@ -77,7 +81,6 @@ endif ifneq ($(findstring darwin,$(CFG_OSTYPE)),) CFG_LIB_NAME=lib$(1).dylib CFG_LIB_GLOB=lib$(1)-*.dylib - CFG_LIB_DSYM_GLOB=lib$(1)-*.dylib.dSYM CFG_UNIXY := 1 CFG_LDENV := DYLD_LIBRARY_PATH CFG_GCCISH_LINK_FLAGS += -dynamiclib -lpthread -framework CoreServices -Wl,-no_compact_unwind From bbd16a0aba779cd10d342ef8f86f97e3767601af Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 14:08:40 -0700 Subject: [PATCH 053/292] Tweak README.txt. --- RELEASES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.txt b/RELEASES.txt index 8d8f9179f6f7..03e058817e20 100644 --- a/RELEASES.txt +++ b/RELEASES.txt @@ -1,7 +1,7 @@ Version 0.4 (October 2012) -------------------------- - * ~1500 changes, numerous bugfixes + * ~2000 changes, numerous bugfixes * Syntax * All keywords are now strict and may not be used as identifiers anywhere From ae861f0288c4773a004967123ad5eb4000989dde Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 14:28:43 -0700 Subject: [PATCH 054/292] Copyedit sections 5 and 6 of the borrowed pointer tutorial --- doc/tutorial-borrowed-ptr.md | 144 ++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 69 deletions(-) diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md index 712c0cba9b42..50d6f9f4c650 100644 --- a/doc/tutorial-borrowed-ptr.md +++ b/doc/tutorial-borrowed-ptr.md @@ -178,25 +178,27 @@ as well as from the managed box, and then compute the distance between them. # Borrowing managed boxes and rooting -We’ve seen a few examples so far where heap boxes (both managed and -unique) are borrowed. Up till this point, we’ve glossed over issues of +We’ve seen a few examples so far of borrowing heap boxes, both managed +and unique. Up till this point, we’ve glossed over issues of safety. As stated in the introduction, at runtime a borrowed pointer -is simply a pointer, nothing more. Therefore, if we wish to avoid the -issues that C has with dangling pointers (and we do!), a compile-time -safety check is required. +is simply a pointer, nothing more. Therefore, avoiding C's problems +with dangling pointers requires a compile-time safety check. -The basis for the check is the notion of _lifetimes_. A lifetime is -basically a static approximation of the period in which the pointer is -valid: it always corresponds to some expression or block within the -program. Within that expression, the pointer can be used freely, but -if the pointer somehow leaks outside of that expression, the compiler -will report an error. We’ll be discussing lifetimes more in the -examples to come, and a more thorough introduction is also available. +The basis for the check is the notion of _lifetimes_. A lifetime is a +static approximation of the span of execution during which the pointer +is valid: it always corresponds to some expression or block within the +program. Code inside that expression can use the pointer without +restrictions. But if the pointer escapes from that expression (for +example, if the expression contains an assignment expression that +assigns the pointer to a mutable field of a data structure with a +broader scope than the pointer itself), the compiler reports an +error. We'll be discussing lifetimes more in the examples to come, and +a more thorough introduction is also available. -When a borrowed pointer is created, the compiler must ensure that it -will remain valid for its entire lifetime. Sometimes this is -relatively easy, such as when taking the address of a local variable -or a field that is stored on the stack: +When the `&` operator creates a borrowed pointer, the compiler must +ensure that the pointer remains valid for its entire +lifetime. Sometimes this is relatively easy, such as when taking the +address of a local variable or a field that is stored on the stack: ~~~ struct X { f: int } @@ -207,12 +209,12 @@ fn example1() { } // -+ ~~~ -Here, the lifetime of the borrowed pointer is simply L, the remainder -of the function body. No extra work is required to ensure that `x.f` -will not be freed. This is true even if `x` is mutated. +Here, the lifetime of the borrowed pointer `y` is simply L, the +remainder of the function body. The compiler need not do any other +work to prove that code will not free `x.f`. This is true even if the +code mutates `x`. -The situation gets more complex when borrowing data that resides in -heap boxes: +The situation gets more complex when borrowing data inside heap boxes: ~~~ # struct X { f: int } @@ -223,20 +225,25 @@ fn example2() { } // -+ ~~~ -In this example, the value `x` is in fact a heap box, and `y` is -therefore a pointer into that heap box. Again the lifetime of `y` will -be L, the remainder of the function body. But there is a crucial -difference: suppose `x` were reassigned during the lifetime L? If -we’re not careful, that could mean that the managed box would become -unrooted and therefore be subject to garbage collection +In this example, the value `x` is a heap box, and `y` is therefore a +pointer into that heap box. Again the lifetime of `y` is L, the +remainder of the function body. But there is a crucial difference: +suppose `x` were to be reassigned during the lifetime L? If the +compiler isn't careful, the managed box could become *unrooted*, and +would therefore be subject to garbage collection. A heap box that is +unrooted is one such that no pointer values in the heap point to +it. It would violate memory safety for the box that was originally +assigned to `x` to be garbage-collected, since a non-heap +pointer---`y`---still points into it. -> ***Note:***In our current implementation, the garbage collector is -> implemented using reference counting and cycle detection. +> ***Note:*** Our current implementation implements the garbage collector +> using reference counting and cycle detection. -For this reason, whenever the interior of a managed box stored in a -mutable location is borrowed, the compiler will insert a temporary -that ensures that the managed box remains live for the entire -lifetime. So, the above example would be compiled as: +For this reason, whenever an `&` expression borrows the interior of a +managed box stored in a mutable location, the compiler inserts a +temporary that ensures that the managed box remains live for the +entire lifetime. So, the above example would be compiled as if it were +written ~~~ # struct X { f: int } @@ -255,9 +262,9 @@ process is called *rooting*. The previous example demonstrated *rooting*, the process by which the compiler ensures that managed boxes remain live for the duration of a -borrow. Unfortunately, rooting does not work if the data being -borrowed is a unique box, as it is not possible to have two references -to a unique box. +borrow. Unfortunately, rooting does not work for borrows of unique +boxes, because it is not possible to have two references to a unique +box. For unique boxes, therefore, the compiler will only allow a borrow *if the compiler can guarantee that the unique box will not be reassigned @@ -280,14 +287,14 @@ fn example3() -> int { ~~~ Here, as before, the interior of the variable `x` is being borrowed -and `x` is declared as mutable. However, the compiler can clearly see -that `x` is not assigned anywhere in the lifetime L of the variable +and `x` is declared as mutable. However, the compiler can prove that +`x` is not assigned anywhere in the lifetime L of the variable `y`. Therefore, it accepts the function, even though `x` is mutable and in fact is mutated later in the function. -It may not be clear why we are so concerned about the variable which -was borrowed being mutated. The reason is that unique boxes are freed -_as soon as their owning reference is changed or goes out of +It may not be clear why we are so concerned about mutating a borrowed +variable. The reason is that the runtime system frees any unique box +_as soon as its owning reference changes or goes out of scope_. Therefore, a program like this is illegal (and would be rejected by the compiler): @@ -332,11 +339,11 @@ Once the reassignment occurs, the memory will look like this: Here you can see that the variable `y` still points at the old box, which has been freed. -In fact, the compiler can apply this same kind of reasoning can be -applied to any memory which is _(uniquely) owned by the stack -frame_. So we could modify the previous example to introduce -additional unique pointers and structs, and the compiler will still be -able to detect possible mutations: +In fact, the compiler can apply the same kind of reasoning to any +memory that is _(uniquely) owned by the stack frame_. So we could +modify the previous example to introduce additional unique pointers +and structs, and the compiler will still be able to detect possible +mutations: ~~~ {.xfail-test} fn example3() -> int { @@ -353,11 +360,11 @@ fn example3() -> int { In this case, two errors are reported, one when the variable `x` is modified and another when `x.f` is modified. Either modification would -cause the pointer `y` to be invalidated. +invalidate the pointer `y`. -Things get tricker when the unique box is not uniquely owned by the -stack frame (or when the compiler doesn’t know who the owner -is). Consider a program like this: +Things get trickier when the unique box is not uniquely owned by the +stack frame, or when there is no way for the compiler to determine the +box's owner. Consider a program like this: ~~~ struct R { g: int } @@ -381,18 +388,18 @@ Here the heap looks something like: +------+ ~~~ -In this case, the owning reference to the value being borrowed is in -fact `x.f`. Moreover, `x.f` is both mutable and aliasable. Aliasable -means that it is possible that there are other pointers to that same -managed box, so even if the compiler were to prevent `x.f` from being -mutated, the field might still be changed through some alias of -`x`. Therefore, to be safe, the compiler only accepts pure actions -during the lifetime of `y`. We’ll have a final example on purity but -inn unique fields, as in the following example: +In this case, the owning reference to the value being borrowed is +`x.f`. Moreover, `x.f` is both mutable and *aliasable*. Aliasable +means that there may be other pointers to that same managed box, so +even if the compiler were to prove an absence of mutations to `x.f`, +code could mutate `x.f` indirectly by changing an alias of +`x`. Therefore, to be safe, the compiler only accepts *pure* actions +during the lifetime of `y`. We define what "pure" means in the section +on [purity](#purity). Besides ensuring purity, the only way to borrow the interior of a -unique found in aliasable memory is to ensure that it is stored within -unique fields, as in the following example: +unique found in aliasable memory is to ensure that the borrowed field +itself is also unique, as in the following example: ~~~ struct R { g: int } @@ -409,7 +416,7 @@ the compiler to know that, even if aliases to `x` exist, the field `f` cannot be changed and hence the unique box `g` will remain valid. If you do have a unique box in a mutable field, and you wish to borrow -it, one option is to use the swap operator to bring that unique box +it, one option is to use the swap operator to move that unique box onto your stack: ~~~ @@ -430,14 +437,13 @@ fn example5c(x: @S) -> int { Of course, this has the side effect of modifying your managed box for the duration of the borrow, so it only works when you know that you -won’t be accessing that same box for the duration of the loan. Note -also that sometimes it is necessary to introduce additional blocks to -constrain the scope of the loan. In this example, the borrowed -pointer `y` would still be in scope when you moved the value `v` back -into `x.f`, and hence moving `v` would be considered illegal. You -cannot move values if they are outstanding loans which are still -valid. By introducing the block, the scope of `y` is restricted and so -the move is legal. +won't be accessing that same box for the duration of the loan. Also, +it is sometimes necessary to introduce additional blocks to constrain +the scope of the loan. In this example, the borrowed pointer `y` +would still be in scope when you moved the value `v` back into `x.f`, +and hence moving `v` would be considered illegal. You cannot move +values if they are the targets of valid outstanding loans. Introducing +the block restricts the scope of `y`, making the move legal. # Borrowing and enums From 448c349234111d2fbe057898fb6435fd8466ffdc Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 14:49:07 -0700 Subject: [PATCH 055/292] Copyedit sections 7 and 8 of the borrowed pointer tutorial --- doc/tutorial-borrowed-ptr.md | 142 ++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 69 deletions(-) diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md index 50d6f9f4c650..f5199a76a40b 100644 --- a/doc/tutorial-borrowed-ptr.md +++ b/doc/tutorial-borrowed-ptr.md @@ -447,11 +447,11 @@ the block restricts the scope of `y`, making the move legal. # Borrowing and enums -The previous example showed that borrowing unique boxes found in -aliasable, mutable memory is not permitted, so as to prevent pointers -into freed memory. There is one other case where the compiler must be -very careful to ensure that pointers remain valid: pointers into the -interior of an enum. +The previous example showed that the type system forbids any borrowing +of unique boxes found in aliasable, mutable memory. This restriction +prevents pointers from pointing into freed memory. There is one other +case where the compiler must be very careful to ensure that pointers +remain valid: pointers into the interior of an `enum`. As an example, let’s look at the following `shape` type that can represent both rectangles and circles: @@ -465,9 +465,9 @@ enum Shape { } ~~~ -Now I might write a function to compute the area of a shape. This -function takes a borrowed pointer to a shape to avoid the need of -copying them. +Now we might write a function to compute the area of a shape. This +function takes a borrowed pointer to a shape, to avoid the need for +copying. ~~~ # struct Point {x: float, y: float}; // as before @@ -485,21 +485,21 @@ fn compute_area(shape: &Shape) -> float { } ~~~ -The first case matches against circles. Here the radius is extracted -from the shape variant and used to compute the area of the circle -(Like any up-to-date engineer, we use the [tau circle constant][tau] -and not that dreadfully outdated notion of pi). +The first case matches against circles. Here, the pattern extracts the +radius from the shape variant and the action uses it to compute the +area of the circle. (Like any up-to-date engineer, we use the [tau +circle constant][tau] and not that dreadfully outdated notion of pi). [tau]: http://www.math.utah.edu/~palais/pi.html The second match is more interesting. Here we match against a -rectangle and extract its size: but rather than copy the `size` struct, -we use a by-reference binding to create a pointer to it. In other -words, a pattern binding like `ref size` in fact creates a pointer of -type `&size` into the _interior of the enum_. +rectangle and extract its size: but rather than copy the `size` +struct, we use a by-reference binding to create a pointer to it. In +other words, a pattern binding like `ref size` binds the name `size` +to a pointer of type `&size` into the _interior of the enum_. -To make this more clear, let’s look at a diagram of how things are -laid out in memory in the case where `shape` points at a rectangle: +To make this more clear, let's look at a diagram of memory layout in +the case where `shape` points at a rectangle: ~~~ {.notrust} Stack Memory @@ -523,8 +523,8 @@ the shape. Perhaps you can see where the danger lies: if the shape were somehow to be reassigned, perhaps to a circle, then although the memory used to store that shape value would still be valid, _it would have a -different type_! This is shown in the following diagram, depicting what -the state of memory would be if shape were overwritten with a circle: +different type_! The following diagram shows what memory would look +like if code overwrote `shape` with a circle: ~~~ {.notrust} Stack Memory @@ -538,20 +538,23 @@ Stack Memory +---------------+ ~~~ -As you can see, the `size` pointer would not be pointing at a `float` and -not a struct. This is not good. +As you can see, the `size` pointer would be pointing at a `float` +instead of a struct. This is not good: dereferencing the second field +of a `float` as if it were a struct with two fields would be a memory +safety violation. So, in fact, for every `ref` binding, the compiler will impose the same rules as the ones we saw for borrowing the interior of a unique -box: it must be able to guarantee that the enum will not be -overwritten for the duration of the borrow. In fact, the example I -gave earlier would be considered safe. This is because the shape -pointer has type `&Shape`, which means “borrowed pointer to immutable -memory containing a shape”. If however the type of that pointer were -`&const Shape` or `&mut Shape`, then the ref binding would not be -permitted. Just as with unique boxes, the compiler will permit ref -bindings into data owned by the stack frame even if it is mutable, but -otherwise it requires that the data reside in immutable memory. +box: it must be able to guarantee that the `enum` will not be +overwritten for the duration of the borrow. In fact, the compiler +would accept the example we gave earlier. The example is safe because +the shape pointer has type `&Shape`, which means "borrowed pointer to +immutable memory containing a `shape`". If, however, the type of that +pointer were `&const Shape` or `&mut Shape`, then the ref binding +would be ill-typed. Just as with unique boxes, the compiler will +permit `ref` bindings into data owned by the stack frame even if the +data are mutable, but otherwise it requires that the data reside in +immutable memory. > ***Note:*** Right now, pattern bindings not explicitly annotated > with `ref` or `copy` use a special mode of "implicit by reference". @@ -560,11 +563,11 @@ otherwise it requires that the data reside in immutable memory. # Returning borrowed pointers -So far, all of the examples we’ve looked at use borrowed pointers in a -“downward” direction. That is, the borrowed pointer is created and -then used during the method or code block which created it. It is also -possible to return borrowed pointers to the caller, but as we'll see -this requires some explicit annotation. +So far, all of the examples we've looked at use borrowed pointers in a +“downward” direction. That is, a method or code block creates a +borrowed pointer, then uses it within the same scope. It is also +possible to return borrowed pointers as the result of a function, but +as we'll see, doing so requires some explicit annotation. For example, we could write a subroutine like this: @@ -573,23 +576,25 @@ struct Point {x: float, y: float} fn get_x(p: &r/Point) -> &r/float { &p.x } ~~~ -Here, the function `get_x()` returns a pointer into the structure it was -given. The type of the parameter (`&r/Point`) and return type (`&r/float`) both -make use of a new syntactic form that we have not seen so far. Here the identifier `r` -serves as an explicit name for the lifetime of the pointer. So in effect -this function is declaring that it takes in a pointer with lifetime `r` and returns -a pointer with that same lifetime. +Here, the function `get_x()` returns a pointer into the structure it +was given. The type of the parameter (`&r/Point`) and return type +(`&r/float`) both use a new syntactic form that we have not seen so +far. Here the identifier `r` names the lifetime of the pointer +explicitly. So in effect, this function declares that it takes a +pointer with lifetime `r` and returns a pointer with that same +lifetime. In general, it is only possible to return borrowed pointers if they -are derived from a borrowed pointer which was given as input to the -procedure. In that case, they will always have the same lifetime as -one of the parameters; named lifetimes are used to indicate which -parameter that is. +are derived from a parameter to the procedure. In that case, the +pointer result will always have the same lifetime as one of the +parameters; named lifetimes indicate which parameter that +is. -In the examples before, function parameter types did not include a -lifetime name. In this case, the compiler simply creates a new, -anonymous name, meaning that the parameter is assumed to have a -distinct lifetime from all other parameters. +In the previous examples, function parameter types did not include a +lifetime name. In those examples, the compiler simply creates a fresh +name for the lifetime automatically: that is, the lifetime name is +guaranteed to refer to a distinct lifetime from the lifetimes of all +other parameters. Named lifetimes that appear in function signatures are conceptually the same as the other lifetimes we've seen before, but they are a bit @@ -599,13 +604,13 @@ lifetime `r` is actually a kind of *lifetime parameter*: it is defined by the caller to `get_x()`, just as the value for the parameter `p` is defined by that caller. -In any case, whatever the lifetime `r` is, the pointer produced by -`&p.x` always has the same lifetime as `p` itself, as a pointer to a +In any case, whatever the lifetime of `r` is, the pointer produced by +`&p.x` always has the same lifetime as `p` itself: a pointer to a field of a struct is valid as long as the struct is valid. Therefore, -the compiler is satisfied with the function `get_x()`. +the compiler accepts the function `get_x()`. -To drill in this point, let’s look at a variation on the example, this -time one which does not compile: +To emphasize this point, let’s look at a variation on the example, this +time one that does not compile: ~~~ {.xfail-test} struct Point {x: float, y: float} @@ -617,22 +622,21 @@ fn get_x_sh(p: @Point) -> &float { Here, the function `get_x_sh()` takes a managed box as input and returns a borrowed pointer. As before, the lifetime of the borrowed pointer that will be returned is a parameter (specified by the -caller). That means that effectively `get_x_sh()` is promising to -return a borrowed pointer that is valid for as long as the caller -would like: this is subtly different from the first example, which -promised to return a pointer that was valid for as long as the pointer -it was given. +caller). That means that `get_x_sh()` promises to return a borrowed +pointer that is valid for as long as the caller would like: this is +subtly different from the first example, which promised to return a +pointer that was valid for as long as its pointer argument was valid. Within `get_x_sh()`, we see the expression `&p.x` which takes the -address of a field of a managed box. This implies that the compiler -must guarantee that, so long as the resulting pointer is valid, the -managed box will not be reclaimed by the garbage collector. But recall -that `get_x_sh()` also promised to return a pointer that was valid for -as long as the caller wanted it to be. Clearly, `get_x_sh()` is not in -a position to make both of these guarantees; in fact, it cannot -guarantee that the pointer will remain valid at all once it returns, -as the parameter `p` may or may not be live in the caller. Therefore, -the compiler will report an error here. +address of a field of a managed box. The presence of this expression +implies that the compiler must guarantee that, so long as the +resulting pointer is valid, the managed box will not be reclaimed by +the garbage collector. But recall that `get_x_sh()` also promised to +return a pointer that was valid for as long as the caller wanted it to +be. Clearly, `get_x_sh()` is not in a position to make both of these +guarantees; in fact, it cannot guarantee that the pointer will remain +valid at all once it returns, as the parameter `p` may or may not be +live in the caller. Therefore, the compiler will report an error here. In general, if you borrow a managed (or unique) box to create a borrowed pointer, the pointer will only be valid within the function From de4687c378b9d83903896ee28413db847644ff77 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 15:04:42 -0700 Subject: [PATCH 056/292] Copyedit sections 9-11 of the borrowed pointer tutorial (last edits from me) --- doc/tutorial-borrowed-ptr.md | 43 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md index f5199a76a40b..921418fa1bda 100644 --- a/doc/tutorial-borrowed-ptr.md +++ b/doc/tutorial-borrowed-ptr.md @@ -647,9 +647,9 @@ points at a static constant). # Named lifetimes -Let's look at named lifetimes in more detail. In effect, the use of -named lifetimes allows you to group parameters by lifetime. For -example, consider this function: +Let's look at named lifetimes in more detail. Named lifetimes allow +for grouping of parameters by lifetime. For example, consider this +function: ~~~ # struct Point {x: float, y: float}; // as before @@ -722,10 +722,10 @@ fn select(shape: &tmp/Shape, threshold: float, } ~~~ -Here you can see the lifetime of shape is now being called `tmp`. The -parameters `a`, `b`, and the return value are all given the lifetime -`r`. However, since the lifetime `tmp` is not returned, it would be shorter -to just omit the named lifetime for `shape` altogether: +Here you can see that `shape`'s lifetime is now named `tmp`. The +parameters `a`, `b`, and the return value all have the lifetime `r`. +However, since the lifetime `tmp` is not returned, it would be more +concise to just omit the named lifetime for `shape` altogether: ~~~ # struct Point {x: float, y: float}; // as before @@ -746,17 +746,22 @@ This is equivalent to the previous definition. # Purity As mentioned before, the Rust compiler offers a kind of escape hatch -that permits borrowing of any data, but only if the actions that occur +that permits borrowing of any data, as long as the actions that occur during the lifetime of the borrow are pure. Pure actions are those -which only modify data owned by the current stack frame. The compiler +that only modify data owned by the current stack frame. The compiler can therefore permit arbitrary pointers into the heap, secure in the knowledge that no pure action will ever cause them to become invalidated (the compiler must still track data on the stack which is -borrowed and enforce those rules normally, of course). +borrowed and enforce those rules normally, of course). A pure function +in Rust is referentially transparent: it returns the same results +given the same (observably equivalent) inputs. That is because while +pure functions are allowed to modify data, they may only modify +*stack-local* data, which cannot be observed outside the scope of the +function itself. (Using an `unsafe` block invalidates this guarantee.) -Let’s revisit a previous example and show how purity can affect the -compiler’s result. Here is `example5a()`, which borrows the interior of -a unique box found in an aliasable, mutable location, only now we’ve +Let’s revisit a previous example and show how purity can affect +typechecking. Here is `example5a()`, which borrows the interior of a +unique box found in an aliasable, mutable location, only now we’ve replaced the `...` with some specific code: ~~~ @@ -768,8 +773,8 @@ fn example5a(x: @S ...) -> int { } ~~~ -The new code simply returns an incremented version of `y`. This clearly -doesn’t do mutate anything in the heap, so the compiler is satisfied. +The new code simply returns an incremented version of `y`. This code +clearly doesn't mutate the heap, so the compiler is satisfied. But suppose we wanted to pull the increment code into a helper, like this: @@ -791,8 +796,8 @@ fn example5a(x: @S ...) -> int { ~~~ But now the compiler will report an error again. The reason is that it -only considers one function at a time (like most type checkers), and -so it does not know that `add_one()` only takes pure actions. We can +only considers one function at a time (like most typecheckers), and +so it does not know that `add_one()` consists of pure code. We can help the compiler by labeling `add_one()` as pure: ~~~ @@ -803,7 +808,7 @@ With this change, the modified version of `example5a()` will again compile. # Conclusion -So there you have it. A (relatively) brief tour of borrowed pointer -system. For more details, I refer to the (yet to be written) reference +So there you have it: a (relatively) brief tour of the borrowed pointer +system. For more details, we refer to the (yet to be written) reference document on borrowed pointers, which will explain the full notation and give more examples. From 194d3786a7a03fa516057e446fc87cbb213d39d5 Mon Sep 17 00:00:00 2001 From: Kevin Cantu Date: Wed, 10 Oct 2012 15:29:01 -0700 Subject: [PATCH 057/292] A simple update to the manpage based on the usage message --- man/rustc.1 | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/man/rustc.1 b/man/rustc.1 index f5888015944a..0e0bfe0f108c 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -1,4 +1,4 @@ -.TH RUSTC "1" "July 2012" "rustc 0.3" "User Commands" +.TH RUSTC "1" "October 2012" "rustc 0.4" "User Commands" .SH NAME rustc \- rust compiler .SH SYNOPSIS @@ -42,6 +42,9 @@ Compile a library crate \fB\-\-ls\fR List the symbols defined by a compiled library crate .TP +\fB\-\-jit\fR +Execute using JIT (experimental) +.TP \fB\-\-no\-trans\fR Run all passes except translation; no output .TP @@ -62,9 +65,9 @@ Parse only; do not compile, assemble, or link .TP \fB\-\-pretty\fR [type] Pretty\-print the input instead of compiling; -valid types are: \fBnormal\fR (un\-annotated source), -\fBexpanded\fR (crates expanded), \fBtyped\fR (crates expanded, -with type annotations), or \fBidentified\fR (fully +valid types are: normal (un\-annotated source), +expanded (crates expanded), typed (crates expanded, +with type annotations), or identified (fully parenthesized, AST nodes and blocks with IDs) .TP \fB\-S\fR @@ -75,7 +78,8 @@ Write intermediate files (.bc, .opt.bc, .o) in addition to normal output .TP \fB\-\-static\fR -Use or produce static libraries or binaries (experimental) +Use or produce static libraries or binaries +(experimental) .TP \fB\-\-sysroot\fR Override the system root @@ -84,21 +88,25 @@ Override the system root Build a test harness .TP \fB\-\-target\fR -Target cpu\-manufacturer\-kernel[\-os] to compile for (default: host triple) -(see <\fBhttp://sources.redhat.com/autobook/autobook/autobook_17.html\fR> for -detail) +Target cpu\-manufacturer\-kernel[\-os] to compile for +(default: host triple) +(see http://sources.redhat.com/autobook/autobook/ +autobook_17.html for detail) +.TP +\-(W|A|D|F) help +Print available 'lint' checks and default settings .TP \fB\-W\fR -enable warning +warn about by default .TP -\fB\-W\fR no\- -disable warning +\fB\-A\fR +allow by default .TP -\fB\-W\fR err\- -enable warning as an error +\fB\-D\fR +deny by default .TP -\fB\-W\fR help -Print available warnings and default settings +\fB\-F\fR +forbid (deny, and deny all overrides) .TP \fB\-Z\fR help list internal options for debugging rustc @@ -117,11 +125,12 @@ To build either with a crate (.rc) file: $ rustc hello.rc .SH "BUGS" -See <\fBhttps://github.com/mozilla/rust/issues\fR> for a list of known bugs. +See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. .SH "AUTHOR" See \fBAUTHORS.txt\fR in the rust source distribution. Graydon Hoare <\fIgraydon@mozilla.com\fR> is the project leader. .SH "COPYRIGHT" -See \fBLICENSE.txt\fR in the rust source distribution. +This work is licensed under MIT-like terms. See \fBLICENSE.txt\fR +in the rust source distribution. From c419e77cc12f0eae2e07097c2deb9a51238bb303 Mon Sep 17 00:00:00 2001 From: Kevin Cantu Date: Wed, 10 Oct 2012 15:45:33 -0700 Subject: [PATCH 058/292] Touchup the debug flag description printing --- src/rustc/driver/rustc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index c60904419d5f..0f191c263fcf 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -113,7 +113,7 @@ fn describe_debug_flags() { io::println(fmt!("\nAvailable debug options:\n")); for session::debugging_opts_map().each |pair| { let (name, desc, _) = *pair; - io::println(fmt!(" -Z%-20s -- %s", name, desc)); + io::println(fmt!(" -Z %-20s -- %s", name, desc)); } } From ae8e6781d2536a3b66d69dfad8f0d5e47eb8617c Mon Sep 17 00:00:00 2001 From: Kevin Cantu Date: Wed, 10 Oct 2012 16:35:52 -0700 Subject: [PATCH 059/292] Move the description of -(W|A|D|F) into the `-W help` message --- man/rustc.1 | 20 ++++---------------- src/rustc/driver/rustc.rs | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/man/rustc.1 b/man/rustc.1 index 0e0bfe0f108c..bb6457dd493e 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -93,23 +93,11 @@ Target cpu\-manufacturer\-kernel[\-os] to compile for (see http://sources.redhat.com/autobook/autobook/ autobook_17.html for detail) .TP -\-(W|A|D|F) help -Print available 'lint' checks and default settings +\fB\-W help\fR +Print 'lint' options and default settings .TP -\fB\-W\fR -warn about by default -.TP -\fB\-A\fR -allow by default -.TP -\fB\-D\fR -deny by default -.TP -\fB\-F\fR -forbid (deny, and deny all overrides) -.TP -\fB\-Z\fR help -list internal options for debugging rustc +\fB\-Z help\fR +Print internal options for debugging rustc .TP \fB\-v\fR \fB\-\-version\fR Print version info and exit diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index 0f191c263fcf..e6a9d726f6d4 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -68,21 +68,21 @@ Options: (default: host triple) (see http://sources.redhat.com/autobook/autobook/ autobook_17.html for detail) - - -(W|A|D|F) help Print available 'lint' checks and default settings - - -W warn about by default - -A allow by default - -D deny by default - -F forbid (deny, and deny all overrides) - - -Z help list internal options for debugging rustc - + -W help Print 'lint' options and default settings + -Z help Print internal options for debugging rustc -v --version Print version info and exit "); } fn describe_warnings() { + io::println(fmt!(" +Available lint options: + -W Warn about + -A Allow + -D Deny + -F Forbid (deny, and deny all overrides) +")); + let lint_dict = lint::get_lint_dict(); let mut max_key = 0; for lint_dict.each_key |k| { max_key = uint::max(k.len(), max_key); } From 056fc13e108a1b610661e0a1c617bda164370807 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 16:31:05 -0700 Subject: [PATCH 060/292] Mention other languages. --- doc/rust.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index f24371cb8d51..98d6277b03dc 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -3109,7 +3109,8 @@ Additional specific influences can be seen from the following languages: * The stack-growth implementation of Go. * The structural algebraic types and compilation manager of SML. * The attribute and assembly systems of C#. -* The deterministic destructor system of C++. +* The references and deterministic destructor system of C++. +* The memory region systems of the ML Kit and Cyclone. * The typeclass system of Haskell. * The lexical identifier rule of Python. * The block syntax of Ruby. From d81a7aba3cc634ae11c412f528591a1647a02de1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 16:34:02 -0700 Subject: [PATCH 061/292] Minor fixes to the runtime and scheduling part of manual. --- doc/rust.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 98d6277b03dc..15e942a74014 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2886,10 +2886,10 @@ non-executing state (blocked, dead) similarly deschedules the task. A call to `core::task::spawn`, passing a 0-argument function as its single argument, causes the runtime to construct a new task executing the passed function. The passed function is referred to as the _entry function_ for -the spawned task, and any captured environment is carries is moved from the +the spawned task, and any captured environment it carries is moved from the spawning task to the spawned task before the spawned task begins execution. -The result of a `spawn` call is a `core::task::task` value. +The result of a `spawn` call is a `core::task::Task` value. An example of a `spawn` call: @@ -2938,16 +2938,20 @@ An example of a *receive*: let s = comm::recv(po); ~~~~~~~~ +Note: this communication system will be replaced by a higher-performance system called "pipes", +in future versions of Rust. + # Runtime services, linkage and debugging -The Rust _runtime_ is a relatively compact collection of C and Rust code +The Rust _runtime_ is a relatively compact collection of C++ and Rust code that provides fundamental services and datatypes to all Rust tasks at run-time. It is smaller and simpler than many modern language runtimes. It is tightly integrated into the language's execution model of memory, tasks, communication and logging. +Note: The runtime library will merge with the `core` library in future versions of Rust. ### Memory allocation From 8f9bb5d2030abf71b42af1898d67446e11678c99 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 16:37:08 -0700 Subject: [PATCH 062/292] Fix markings about future in manual, remove out-of-date marker. --- doc/rust.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 15e942a74014..f6aca3ba1e33 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -41,9 +41,6 @@ If you have suggestions to make, please try to focus them on *reductions* to the language: possible features that can be combined or omitted. We aim to keep the size and complexity of the language under control. -> **Note:** This manual is very out of date. The best source of Rust -> documentation is currently the tutorial. - > **Note:** The grammar for Rust given in this document is rough and > very incomplete; only a modest number of sections have accompanying grammar > rules. Formalizing the grammar accepted by the Rust parser is ongoing work, @@ -1370,10 +1367,8 @@ mod bar { fn add(x: int, y: int) { x + y } ~~~~~~~~ -In future versions of Rust, user-provided extensions to the compiler will be -able to interpret attributes. When this facility is provided, the compiler -will distinguish will be made between language-reserved and user-available -attributes. +> **Note:** In future versions of Rust, user-provided extensions to the compiler will be able to interpret attributes. +> When this facility is provided, the compiler will distinguish between language-reserved and user-available attributes. At present, only the Rust compiler interprets attributes, so all attribute names are effectively reserved. Some significant attributes include: @@ -2938,8 +2933,8 @@ An example of a *receive*: let s = comm::recv(po); ~~~~~~~~ -Note: this communication system will be replaced by a higher-performance system called "pipes", -in future versions of Rust. +> **Note:** this communication system will be replaced by a higher-performance system called "pipes", +> in future versions of Rust. # Runtime services, linkage and debugging @@ -2951,7 +2946,7 @@ run-time. It is smaller and simpler than many modern language runtimes. It is tightly integrated into the language's execution model of memory, tasks, communication and logging. -Note: The runtime library will merge with the `core` library in future versions of Rust. +> **Note:** The runtime library will merge with the `core` library in future versions of Rust. ### Memory allocation From 19f1c3174f77f4ae50d3869697b0aacffba2fc84 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 16:38:12 -0700 Subject: [PATCH 063/292] Remove mention of block-comment nesting. --- doc/rust.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index f6aca3ba1e33..7a99835f522b 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -157,13 +157,13 @@ Some productions are defined by exclusion of particular Unicode characters: ~~~~~~~~ {.ebnf .gram} comment : block_comment | line_comment ; block_comment : "/*" block_comment_body * "*/" ; -block_comment_body : block_comment | non_star * | '*' non_slash ; +block_comment_body : non_star * | '*' non_slash ; line_comment : "//" non_eol * ; ~~~~~~~~ -Comments in Rust code follow the general C++ style of line and block-comment -forms, with proper nesting of block-comment delimiters. Comments are -interpreted as a form of whitespace. +Comments in Rust code follow the general C++ style of line and block-comment forms, +with no nesting of block-comment delimiters. +Comments are interpreted as a form of whitespace. ## Whitespace From 58807b05007b627606a8466c9559fac45970a2eb Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 16:51:11 -0700 Subject: [PATCH 064/292] Mention doc comments. --- doc/rust.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 7a99835f522b..98978e492cf3 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -163,7 +163,13 @@ line_comment : "//" non_eol * ; Comments in Rust code follow the general C++ style of line and block-comment forms, with no nesting of block-comment delimiters. -Comments are interpreted as a form of whitespace. + +Line comments beginning with _three_ slashes (`///`), +and block comments beginning with a repeated asterisk in the block-open sequence (`/**`), +are interpreted as a special syntax for `doc` [attributes](#attributes). +That is, they are equivalent to writing `#[doc "..."]` around the comment's text. + +Non-doc comments are interpreted as a form of whitespace. ## Whitespace From c639f44adbb6652232650084df15422093ed4f56 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 17:08:10 -0700 Subject: [PATCH 065/292] Tidy up macro_rules grammar. --- doc/rust.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 98978e492cf3..29b99dd587f4 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -478,11 +478,8 @@ with values. `proto!` is an item, defining a new name. ## Macros -User-defined syntax extensions are called "macros", and they can be defined -with the `macro_rules!` syntax extension. User-defined macros can currently -only be invoked in expression position. +~~~~~~~~ {.ebnf .gram} -~~~~ {.ebnf .gram} expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';' matcher : '(' matcher * ')' | '[' matcher * ']' @@ -494,13 +491,18 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']' | '$' '(' transcriber * ')' sep_token? [ '*' | '+' ] | non_special_token -~~~~ +~~~~~~~~ + +User-defined syntax extensions are called "macros", and they can be defined +with the `macro_rules!` syntax extension. User-defined macros can currently +only be invoked in expression position. + (A `sep_token` is any token other than `*` and `+`. A `non_special_token` is any token other than a delimiter or `$`.) Macro invocations are looked up by name, and each macro rule is tried in turn; the first successful match is transcribed. The matching and transcribing -processes are close cousins, and will be described together: +processes are closely related, and will be described together: ### Macro By Example From 304a2455c07fd66abbf3a110c953d0f47ecdec74 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 17:08:21 -0700 Subject: [PATCH 066/292] Mention deprecation of crate files. --- doc/rust.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/rust.md b/doc/rust.md index 29b99dd587f4..83d0b886e9d1 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -591,6 +591,9 @@ Crates are provided to the Rust compiler through two kinds of file: - _crate files_, that end in `.rc` and each define a `crate`. - _source files_, that end in `.rs` and each define a `module`. +> **Note:** The functionality of crate files will be merged into source files in future versions of Rust. +> The separate processing of crate files, both their grammar and file extension, will be removed. + The Rust compiler is always invoked with a single input file, and always produces a single output crate. From ff37c65f5ca5d704c7cfb98fe11a7e09d7b983e1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 17:09:07 -0700 Subject: [PATCH 067/292] Remove mention of argv. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 83d0b886e9d1..3adc6382c3b9 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -677,7 +677,7 @@ a referencing crate file, or by the filename of the source file itself. A source file that contains a `main` function can be compiled to an executable. If a `main` function is present, it must have no [type parameters](#type-parameters) -and no [constraints](#constraints). Its return type must be [`nil`](#primitive-types) and it must either have no arguments, or a single argument of type `[~str]`. +and no [constraints](#constraints). Its return type must be [`nil`](#primitive-types) and it must take no arguments. # Items and attributes From cad6733db5199f35cc64334aa53b635668635931 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 17:10:23 -0700 Subject: [PATCH 068/292] Remove mention of res_item, add const_item. Reword a bit. --- doc/rust.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 3adc6382c3b9..f8d3e6044e96 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -681,14 +681,14 @@ and no [constraints](#constraints). Its return type must be [`nil`](#primitive-t # Items and attributes -A crate is a collection of [items](#items), each of which may have some number -of [attributes](#attributes) attached to it. +Crates contain [items](#items), +each of which may have some number of [attributes](#attributes) attached to it. ## Items ~~~~~~~~ {.ebnf .gram} item : mod_item | fn_item | type_item | enum_item - | res_item | trait_item | impl_item | foreign_mod_item ; + | const_item | trait_item | impl_item | foreign_mod_item ; ~~~~~~~~ An _item_ is a component of a crate; some module items can be defined in crate From 3d31a6b8991005525d55226099d8c8457a0739f6 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 10 Oct 2012 17:18:01 -0700 Subject: [PATCH 069/292] Remove several references to resources; add section for Constants. --- doc/rust.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index f8d3e6044e96..9d2e12fde845 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -706,7 +706,7 @@ There are several kinds of item: * [functions](#functions) * [type definitions](#type-definitions) * [enumerations](#enumerations) - * [resources](#resources) + * [constants](#constants) * [traits](#traits) * [implementations](#implementations) @@ -1151,6 +1151,18 @@ enum list { let a: list = cons(7, @cons(13, @nil)); ~~~~ +### Constants + +~~~~~~~~ {.ebnf .gram} +const_item : "const" ident ':' type '=' expr ';' ; +~~~~~~~~ + +A Constant is a named value stored in read-only memory in a crate. +The value bound to a constant is evaluated at compile time. +Constants are declared with the `const` keyword. +A constant item must have an expression giving its definition. +The definition expression of a constant is limited to expression forms that can be evaluated at compile time. + ### Traits A _trait item_ describes a set of method types. [_implementation @@ -1425,7 +1437,7 @@ statement block. The declared name may denote a new slot or a new item. An _item declaration statement_ has a syntactic form identical to an [item](#items) declaration within a module. Declaring an item -- a function, -enumeration, type, resource, trait, implementation or module -- locally +enumeration, type, constant, 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. @@ -1629,8 +1641,7 @@ operators, before the expression they apply to. `-` : Negation. May only be applied to numeric types. `*` - : Dereference. When applied to a [box](#box-types) or - [resource](#resources) type, it accesses the inner value. For + : Dereference. When applied to a [pointer](#pointer-types) it denotes the pointed-to location. For mutable boxes, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to. For [enums](#enumerated-types) that have only a single variant, containing a single parameter, the dereference operator accesses @@ -2185,7 +2196,7 @@ fail_expr : "fail" expr ? ; Evaluating a `fail` expression causes a task to enter the *failing* state. In the *failing* state, a task unwinds its stack, destroying all frames and -freeing all resources until it reaches its entry frame, at which point it +running all destructors until it reaches its entry frame, at which point it halts execution in the *dead* state. From b7b22179761a71df4ec77185b54f134601130592 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 10 Oct 2012 17:56:23 -0700 Subject: [PATCH 070/292] Update tutorial install instructions --- doc/tutorial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 59117d339a1d..e01e50a93942 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -71,7 +71,7 @@ Snapshot binaries are currently built and tested on several platforms: * Windows (7, Server 2008 R2), x86 only * Linux (various distributions), x86 and x86-64 -* OSX 10.6 ("Snow Leopard") or 10.7 ("Lion"), x86 and x86-64 +* OSX 10.6 ("Snow Leopard") or greater, x86 and x86-64 You may find that other platforms work, but these are our "tier 1" supported build environments that are most likely to work. @@ -79,7 +79,7 @@ supported build environments that are most likely to work. > ***Note:*** Windows users should read the detailed > [getting started][wiki-start] notes on the wiki. Even when using > the binary installer the Windows build requires a MinGW installation, -> the precise details of which are not discussed in this tutorial. +> the precise details of which are not discussed here. To build from source you will also need the following prerequisite packages: From 4c833af038bec879c8124520c68e7f27034d41ab Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 10 Oct 2012 17:56:38 -0700 Subject: [PATCH 071/292] Copy README install instructions from tutorial --- README.md | 63 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index e52b85c79693..9f875ac346e1 100644 --- a/README.md +++ b/README.md @@ -6,52 +6,61 @@ documentation. ## Installation -The Rust compiler is slightly unusual in that it is written in Rust and -therefore must be built by a precompiled "snapshot" version of itself (made in -an earlier state of development). As such, source builds require that: +The Rust compiler currently must be built from a [tarball], unless you +are on Windows, in which case using the [installer][win-exe] is +recommended. -* You are connected to the internet, to fetch snapshots. +Since the Rust compiler is written in Rust, it must be built by +a precompiled "snapshot" version of itself (made in an earlier state +of development). As such, source builds require a connection to +the Internet, to fetch snapshots, and an OS that can execute the +available snapshot binaries. -* You can at least execute snapshot binaries of one of the forms we offer - them in. Currently we build and test snapshots on: +Snapshot binaries are currently built and tested on several platforms: - * Windows (7, server 2008 r2) x86 only - * Linux 2.6.x (various distributions) x86 and x86-64 - * OSX 10.6 ("Snow Leopard") or 10.7 ("Lion") x86 and x86-64 +* Windows (7, Server 2008 R2), x86 only +* Linux (various distributions), x86 and x86-64 +* OSX 10.6 ("Snow Leopard") or greater, x86 and x86-64 -You may find other platforms work, but these are our "tier 1" supported build -environments that are most likely to work. Further platforms will be added to -the list in the future via cross-compilation. +You may find that other platforms work, but these are our "tier 1" +supported build environments that are most likely to work. -To build from source you will also need the following prerequisite packages: +> ***Note:*** Windows users should read the detailed +> [getting started][wiki-start] notes on the wiki. Even when using +> the binary installer the Windows build requires a MinGW installation, +> the precise details of which are not discussed here. + +To build from source you will also need the following prerequisite +packages: * g++ 4.4 or clang++ 3.x -* python 2.6 or later +* python 2.6 or later (but not 3.x) * perl 5.0 or later * gnu make 3.81 or later * curl -Assuming you're on a relatively modern Linux/OSX system and have met the -prerequisites, something along these lines should work: +Assuming you're on a relatively modern *nix system and have met the +prerequisites, something along these lines should work. + $ wget http://dl.rust-lang.org/dist/rust-0.4.tar.gz $ tar -xzf rust-0.4.tar.gz $ cd rust-0.4 $ ./configure $ make && make install -When complete, make install will place the following programs into -/usr/local/bin: +You may need to use `sudo make install` if you do not normally have +permission to modify the destination directory. The install locations +can be adjusted by passing a `--prefix` argument to +`configure`. Various other options are also supported, pass `--help` +for more information on them. -* rustc, the Rust compiler -* rustdoc, the API-documentation tool -* cargo, the Rust package manager +When complete, `make install` will place several programs into +`/usr/local/bin`: `rustc`, the Rust compiler; `rustdoc`, the +API-documentation tool, and `cargo`, the Rust package manager. -In addition to a manual page under /usr/local/share/man and a set of host and -target libraries under /usr/local/lib/rustc. - -The install locations can be adjusted by passing a --prefix argument to -configure. Various other options are also supported, pass --help for more -information on them. +[wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust +[tarball]: http://dl.rust-lang.org/dist/rust-0.4.tar.gz +[win-exe]: http://dl.rust-lang.org/dist/rust-0.4-install.exe ## License From 38ccaed4ce0892bfa36c210302c42de1aa4dd584 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 19:05:13 -0700 Subject: [PATCH 072/292] Copyedit sections 1 and 2 of tutorial --- doc/tutorial.md | 61 +++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index e01e50a93942..0ff229271761 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -4,7 +4,7 @@ Rust is a programming language with a focus on type safety, memory safety, concurrency and performance. It is intended for writing -large-scale, high-performance software while preventing several +large-scale, high-performance software that is free from several classes of common errors. Rust has a sophisticated memory model that encourages efficient data structures and safe concurrency patterns, forbidding invalid memory accesses that would otherwise cause @@ -18,13 +18,14 @@ pleasant high-level features include: * **Type inference.** Type annotations on local variable declarations are optional. * **Safe task-based concurrency.** Rust's lightweight tasks do not share - memory and communicate through messages. + memory, instead communicating through messages. * **Higher-order functions.** Efficient and flexible closures provide iteration and other control structures * **Pattern matching and algebraic data types.** Pattern matching on - Rust's enums is a compact and expressive way to encode program - logic. -* **Polymorphism.** Rust has type-parameric functions and + Rust's enumeration types (a more powerful version of C's enums, + similar to algebraic data types in functional languages) is a + compact and expressive way to encode program logic. +* **Polymorphism.** Rust has type-parametric functions and types, type classes and OO-style interfaces. ## Scope @@ -35,23 +36,23 @@ type system and memory model, generics, and modules. [Additional tutorials](#what-next) cover specific language features in greater depth. -It assumes the reader is familiar with the basic concepts of +This tutorial assumes that the reader is familiar with the basic concepts of programming, and has programmed in one or more other languages -before. It will often make comparisons to other languages, +before. We will often compare Rust to other languages, particularly those in the C family. ## Conventions -Throughout the tutorial, words that indicate language keywords or -identifiers defined in example code are displayed in `code font`. +Throughout the tutorial, language keywords and identifiers defined in +example code are displayed in `code font`. Code snippets are indented, and also shown in a monospaced font. Not all snippets constitute whole programs. For brevity, we'll often show fragments of programs that don't compile on their own. To try them out, you might have to wrap them in `fn main() { ... }`, and make sure -they don't contain references to things that aren't actually defined. +they don't contain references to names that aren't actually defined. -> ***Warning:*** Rust is a language under heavy development. Notes +> ***Warning:*** Rust is a language under ongoing development. Notes > about potential changes to the language, implementation > deficiencies, and other caveats appear offset in blockquotes. @@ -77,9 +78,14 @@ You may find that other platforms work, but these are our "tier 1" supported build environments that are most likely to work. > ***Note:*** Windows users should read the detailed -> [getting started][wiki-start] notes on the wiki. Even when using -> the binary installer the Windows build requires a MinGW installation, -> the precise details of which are not discussed here. +> "[getting started][wiki-start]" notes on the wiki. Even when using +> the binary installer, the Windows build requires a MinGW installation, +> the precise details of which are not discussed here. Finally, `rustc` may +> need to be [referred to as `rustc.exe`][bug-3319]. It's a bummer, I +> know. + +[bug-3319]: https://github.com/mozilla/rust/issues/3319 +[wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust To build from source you will also need the following prerequisite packages: @@ -90,8 +96,8 @@ packages: * gnu make 3.81 or later * curl -Assuming you're on a relatively modern *nix system and have met the -prerequisites, something along these lines should work. +If you've fulfilled those prerequisites, something along these lines +should work. ~~~~ {.notrust} $ wget http://dl.rust-lang.org/dist/rust-0.4.tar.gz @@ -104,7 +110,7 @@ $ make && make install You may need to use `sudo make install` if you do not normally have permission to modify the destination directory. The install locations can be adjusted by passing a `--prefix` argument to -`configure`. Various other options are also supported, pass `--help` +`configure`. Various other options are also supported: pass `--help` for more information on them. When complete, `make install` will place several programs into @@ -130,10 +136,10 @@ If the Rust compiler was installed successfully, running `rustc hello.rs` will produce an executable called `hello` (or `hello.exe` on Windows) which, upon running, will likely do exactly what you expect. -The Rust compiler tries to provide useful information when it runs -into an error. If you modify the program to make it invalid (for -example, by changing `io::println` to some nonexistent function), and -then compile it, you'll see an error message like this: +The Rust compiler tries to provide useful information when it encounters an +error. If you introduce an error into the program (for example, by changing +`io::println` to some nonexistent function), and then compile it, you'll see +an error message like this: ~~~~ {.notrust} hello.rs:2:4: 2:16 error: unresolved name: io::print_with_unicorns @@ -144,19 +150,10 @@ hello.rs:2 io::print_with_unicorns("hello? yes, this is rust"); In its simplest form, a Rust program is a `.rs` file with some types and functions defined in it. If it has a `main` function, it can be compiled to an executable. Rust does not allow code that's not a -declaration to appear at the top level of the file—all statements must +declaration to appear at the top level of the file: all statements must live inside a function. Rust programs can also be compiled as libraries, and included in other programs. -> ***Note:*** There are some 'gotchas' to be aware of on -> Windows. First, the MinGW environment must be set up -> perfectly. Please read [the wiki][wiki-started]. Second, `rustc` may -> need to be [referred to as `rustc.exe`][bug-3319]. It's a bummer, I -> know. - -[bug-3319]: https://github.com/mozilla/rust/issues/3319 -[wiki-started]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust - ## Editing Rust code There are vim highlighting and indentation scripts in the Rust source @@ -170,7 +167,7 @@ Sublime Text 2, available both [standalone][sublime] and through under `src/etc/kate`. There is ctags support via `src/etc/ctags.rust`, but many other -tools and editors are not provided for yet. If you end up writing a Rust +tools and editors are not yet supported. If you end up writing a Rust mode for your favorite editor, let us know so that we can link to it. [sublime]: http://github.com/dbp/sublime-rust From 6627ac662386541737ab26e3a1c633dc88185c62 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 19:32:11 -0700 Subject: [PATCH 073/292] Copyedit section 3 of tutorial --- doc/tutorial.md | 98 ++++++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 0ff229271761..2d43d19deffd 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -184,8 +184,8 @@ and mostly have the same precedence as in C; comments are again like C. The main surface difference to be aware of is that the condition at the head of control structures like `if` and `while` do not require -paretheses, while their bodies *must* be wrapped in -brackets. Single-statement, bracket-less bodies are not allowed. +parentheses, while their bodies *must* be wrapped in +braces. Single-statement, unbraced bodies are not allowed. ~~~~ # fn recalibrate_universe() -> bool { true } @@ -200,9 +200,9 @@ fn main() { } ~~~~ -The `let` keyword introduces a local variable. Variables are immutable -by default, so `let mut` can be used to introduce a local variable -that can be reassigned. +The `let` keyword introduces a local variable. Variables are immutable by +default. To introduce a local variable that you can re-assign later, use `let +mut` instead. ~~~~ let hi = "hi"; @@ -224,14 +224,14 @@ let imaginary_size = monster_size * 10.0; let monster_size: int = 50; ~~~~ -Local variables may shadow earlier declarations, as in the previous -example in which `monster_size` is first declared as a `float` -then a second `monster_size` is declared as an int. If you were to actually -compile this example though, the compiler will see that the second -`monster_size` is unused, assume that you have made a mistake, and issue -a warning. For occasions where unused variables are intentional, their -name may be prefixed with an underscore to silence the warning, like -`let _monster_size = 50;`. +Local variables may shadow earlier declarations, as in the previous example: +`monster_size` was first declared as a `float`, and then then a second +`monster_size` was declared as an int. If you were to actually compile this +example, though, the compiler will determine that the second `monster_size` is +unused and issue a warning (because this situation is likely to indicate a +programmer error). For occasions where unused variables are intentional, their +name may be prefixed with an underscore to silence the warning, like `let +_monster_size = 50;`. Rust identifiers follow the same rules as C; they start with an alphabetic character or an underscore, and after that may contain any sequence of @@ -278,10 +278,10 @@ let price = }; ~~~~ -Both pieces of code are exactly equivalent—they assign a value to +Both pieces of code are exactly equivalent: they assign a value to `price` depending on the condition that holds. Note that there -are not semicolons in the blocks of the second snippet. This is -important; the lack of a semicolon after the last statement in a +are no semicolons in the blocks of the second snippet. This is +important: the lack of a semicolon after the last statement in a braced block gives the whole block the value of that last expression. Put another way, the semicolon in Rust *ignores the value of an expression*. @@ -290,8 +290,10 @@ would simply assign `()` (nil or void) to `price`. But without the semicolon, ea branch has a different value, and `price` gets the value of the branch that was taken. -In short, everything that's not a declaration (`let` for variables, -`fn` for functions, et cetera) is an expression, including function bodies. +In short, everything that's not a declaration (declarations are `let` for +variables, `fn` for functions, and any top-level named items such as +[traits](#traits), [enum types](#enums), and [constants](#constants)) is an +expression, including function bodies. ~~~~ fn is_four(x: int) -> bool { @@ -314,7 +316,7 @@ something—in which case you'll have embedded it in a bigger statement. # fn foo() -> bool { true } # fn bar() -> bool { true } # fn baz() -> bool { true } -// `let` is not an expression, so it is semi-colon terminated; +// `let` is not an expression, so it is semicolon-terminated; let x = foo(); // When used in statement position, bracy expressions do not @@ -346,7 +348,7 @@ This may sound intricate, but it is super-useful and will grow on you. The basic types include the usual boolean, integral, and floating-point types. ------------------------- ----------------------------------------------- -`()` Nil, the type that has only a single value +`()` Unit, the type that has only a single value `bool` Boolean type, with values `true` and `false` `int`, `uint` Machine-pointer-sized signed and unsigned integers `i8`, `i16`, `i32`, `i64` Signed integers with a specific size (in bits) @@ -394,10 +396,15 @@ type MonsterSize = uint; This will provide a synonym, `MonsterSize`, for unsigned integers. It will not actually create a new, incompatible type—`MonsterSize` and `uint` can be used interchangeably, and using one where the other is expected is not a type -error. +error. In that sense, types declared with `type` are *structural*: their +meaning follows from their structure, and their names are irrelevant in the +type system. -To create data types which are not synonyms, `struct` and `enum` -can be used. They're described in more detail below, but they look like this: +Sometimes, you want your data types to be *nominal* instead of structural: you +want their name to be part of their meaning, so that types with the same +structure but different names are not interchangeable. Rust has two ways to +create nominal data types: `struct` and `enum`. They're described in more +detail below, but they look like this: ~~~~ enum HidingPlaces { @@ -416,12 +423,12 @@ enum MonsterSize = uint; // a single-variant enum ## Literals -Integers can be written in decimal (`144`), hexadecimal (`0x90`), and +Integers can be written in decimal (`144`), hexadecimal (`0x90`), or binary (`0b10010000`) base. Each integral type has a corresponding literal suffix that can be used to indicate the type of a literal: `i` for `int`, `u` for `uint`, and `i8` for the `i8` type, etc. -In the absense of an integer literal suffix, Rust will infer the +In the absence of an integer literal suffix, Rust will infer the integer type based on type annotations and function signatures in the surrounding program. In the absence of any type information at all, Rust will assume that an unsuffixed integer literal has type @@ -439,10 +446,10 @@ a suffix, the literal is assumed to be of type `float`. Suffixes `f32` (32-bit) and `f64` (64-bit) can be used to create literals of a specific type. -The nil literal is written just like the type: `()`. The keywords +The unit literal is written just like the type: `()`. The keywords `true` and `false` produce the boolean literals. -Character literals are written between single quotes, as in `'x'`. Just as in +Character literals are written between single quotes, as in `'x'`. Just like C, Rust understands a number of character escapes, using the backslash character, such as `\n`, `\r`, and `\t`. String literals, written between double quotes, allow the same escape sequences. Rust strings @@ -450,13 +457,13 @@ may contain newlines. ## Constants -Compile-time constants are declared with `const`. All scalar types, -like integers and floats, may be declared `const`, as well as fixed -length vectors, static strings (more on this later), and structs. -Constants may be declared in any scope and may refer to other -constants. Constant declarations are not type inferred, so must always -have a type annotation. By convention they are written in all capital -letters. +Compile-time constants are declared with `const`. A constant may have any +scalar type (for example, integer or float). Other allowable constant types +are fixed-length vectors, static strings (more on this later), and +structs. Constants may be declared in any scope and may refer to other +constants. The compiler does not infer types for constants, so constants must +always be declared with a type annotation. By convention, they are written in +all capital letters. ~~~ // Scalars can be constants @@ -480,7 +487,7 @@ const MY_STRUCTY_PASSWORD: Password = Password { value: MY_PASSWORD }; Rust's set of operators contains very few surprises. Arithmetic is done with `*`, `/`, `%`, `+`, and `-` (multiply, divide, remainder, plus, minus). `-` is -also a unary prefix operator that does negation. As in C, the bit operators +also a unary prefix operator that negates numbers. As in C, the bit operators `>>`, `<<`, `&`, `|`, and `^` are also supported. Note that, if applied to an integer value, `!` flips all the bits (like `~` in @@ -502,21 +509,21 @@ assert y == 4u; ~~~~ The main difference with C is that `++` and `--` are missing, and that -the logical bitwise operators have higher precedence — in C, `x & 2 > 0` +the logical bitwise operators have higher precedence—in C, `x & 2 > 0` means `x & (2 > 0)`, but in Rust, it means `(x & 2) > 0`, which is -more likely what a novice expects. +more likely to be what a novice expects. ## Syntax extensions *Syntax extensions* are special forms that are not built into the language, but are instead provided by the libraries. To make it clear to the reader when -a syntax extension is being used, the names of all syntax extensions end with -`!`. The standard library defines a few syntax extensions, the most useful of -which is `fmt!`, a `sprintf`-style text formatter that is expanded at compile -time. +a name refers to a syntax extension, the names of all syntax extensions end +with `!`. The standard library defines a few syntax extensions, the most +useful of which is `fmt!`, a `sprintf`-style text formatter that an early +compiler phase expands statically. -`fmt!` supports most of the directives that [printf][pf] supports, but -will give you a compile-time error when the types of the directives +`fmt!` supports most of the directives that [printf][pf] supports, but unlike +printf, will give you a compile-time error when the types of the directives don't match the types of the arguments. ~~~~ @@ -530,8 +537,9 @@ io::println(fmt!("what is this thing: %?", mystery_object)); [pf]: http://en.cppreference.com/w/cpp/io/c/fprintf -You can define your own syntax extensions with the macro system, which is out -of scope of this tutorial. +You can define your own syntax extensions with the macro system. For details, see the [macro tutorial][macros]. + +[macros]: tutorial-macros.html # Control structures From d7b8512eae0f92e64b8a9eabe8584ac18bf9e061 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 20:08:08 -0700 Subject: [PATCH 074/292] Copyedit section 4 of tutorial --- doc/tutorial.md | 91 ++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 2d43d19deffd..1695977e6277 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -545,8 +545,8 @@ You can define your own syntax extensions with the macro system. For details, se ## Conditionals -We've seen `if` pass by a few times already. To recap, braces are -compulsory, an optional `else` clause can be appended, and multiple +We've seen `if` expressions a few times already. To recap, braces are +compulsory, an `if` can have an optional `else` clause, and multiple `if`/`else` constructs can be chained together: ~~~~ @@ -559,10 +559,10 @@ if false { } ~~~~ -The condition given to an `if` construct *must* be of type boolean (no -implicit conversion happens). If the arms return a value, this value -must be of the same type for every arm in which control reaches the -end of the block: +The condition given to an `if` construct *must* be of type `bool` (no +implicit conversion happens). If the arms are blocks that have a +value, this value must be of the same type for every arm in which +control reaches the end of the block: ~~~~ fn signum(x: int) -> int { @@ -575,9 +575,10 @@ fn signum(x: int) -> int { ## Pattern matching Rust's `match` construct is a generalized, cleaned-up version of C's -`switch` construct. You provide it with a value and a number of *arms*, -each labelled with a pattern, and the code will attempt to match each pattern -in order. For the first one that matches, the arm is executed. +`switch` construct. You provide it with a value and a number of +*arms*, each labelled with a pattern, and the code compares the value +against each pattern in order until one matches. The matching pattern +executes its corresponding arm. ~~~~ # let my_number = 1; @@ -589,15 +590,19 @@ match my_number { } ~~~~ -There is no 'falling through' between arms, as in C—only one arm is -executed, and it doesn't have to explicitly `break` out of the +Unlike in C, there is no 'falling through' between arms: only one arm +executes, and it doesn't have to explicitly `break` out of the construct when it is finished. -The part to the left of the arrow `=>` is called the *pattern*. Literals are -valid patterns and will match only their own value. The pipe operator -(`|`) can be used to assign multiple patterns to a single arm. Ranges -of numeric literal patterns can be expressed with two dots, as in `M..N`. The -underscore (`_`) is a wildcard pattern that matches everything. +A `match` arm consists of a *pattern*, then an arrow `=>`, followed by +an *action* (expression). Literals are valid patterns and match only +their own value. A single arm may match multiple different patterns by +combining them with the pipe operator (`|`), so long as every pattern +binds the same set of variables. Ranges of numeric literal patterns +can be expressed with two dots, as in `M..N`. The underscore (`_`) is +a wildcard pattern that matches any single value. The asterisk (`*`) +is a different wildcard that can match one or more fields in an `enum` +variant. The patterns in an match arm are followed by a fat arrow, `=>`, then an expression to evaluate. Each case is separated by commas. It's often @@ -612,13 +617,14 @@ match my_number { } ~~~ -`match` constructs must be *exhaustive*: they must have an arm covering every -possible case. For example, if the arm with the wildcard pattern was left off -in the above example, the typechecker would reject it. +`match` constructs must be *exhaustive*: they must have an arm +covering every possible case. For example, the typechecker would +reject the previous example if the arm with the wildcard pattern was +omitted. -A powerful application of pattern matching is *destructuring*, where -you use the matching to get at the contents of data types. Remember -that `(float, float)` is a tuple of two floats: +A powerful application of pattern matching is *destructuring*: +matching in order to bind names to the contents of data +types. Remember that `(float, float)` is a tuple of two floats: ~~~~ fn angle(vector: (float, float)) -> float { @@ -631,37 +637,39 @@ fn angle(vector: (float, float)) -> float { } ~~~~ -A variable name in a pattern matches everything, *and* binds that name -to the value of the matched thing inside of the arm block. Thus, `(0f, +A variable name in a pattern matches any value, *and* binds that name +to the value of the matched value inside of the arm's action. Thus, `(0f, y)` matches any tuple whose first element is zero, and binds `y` to the second element. `(x, y)` matches any tuple, and binds both -elements to a variable. +elements to variables. -Any `match` arm can have a guard clause (written `if EXPR`), which is -an expression of type `bool` that determines, after the pattern is -found to match, whether the arm is taken or not. The variables bound -by the pattern are available in this guard expression. +Any `match` arm can have a guard clause (written `if EXPR`), called a +*pattern guard*, which is an expression of type `bool` that +determines, after the pattern is found to match, whether the arm is +taken or not. The variables bound by the pattern are in scope in this +guard expression. The first arm in the `angle` example shows an +example of a pattern guard. You've already seen simple `let` bindings, but `let` is a little -fancier than you've been led to believe. It too supports destructuring -patterns. For example, you can say this to extract the fields from a -tuple, introducing two variables, `a` and `b`. +fancier than you've been led to believe. It, too, supports destructuring +patterns. For example, you can write this to extract the fields from a +tuple, introducing two variables at once: `a` and `b`. ~~~~ # fn get_tuple_of_two_ints() -> (int, int) { (1, 1) } let (a, b) = get_tuple_of_two_ints(); ~~~~ -Let bindings only work with _irrefutable_ patterns, that is, patterns +Let bindings only work with _irrefutable_ patterns: that is, patterns that can never fail to match. This excludes `let` from matching -literals and most enum variants. +literals and most `enum` variants. ## Loops -`while` produces a loop that runs as long as its given condition -(which must have type `bool`) evaluates to true. Inside a loop, the -keyword `break` can be used to abort the loop, and `loop` can be used -to abort the current iteration and continue with the next. +`while` denotes a loop that iterates as long as its given condition +(which must have type `bool`) evaluates to `true`. Inside a loop, the +keyword `break` aborts the loop, and `loop` aborts the current +iteration and continues with the next. ~~~~ let mut cake_amount = 8; @@ -670,7 +678,7 @@ while cake_amount > 0 { } ~~~~ -`loop` is the preferred way of writing `while true`: +`loop` denotes an infinite loop, and is the preferred way of writing `while true`: ~~~~ let mut x = 5; @@ -684,9 +692,8 @@ loop { This code prints out a weird sequence of numbers and stops as soon as it finds one that can be divided by five. -For more involved iteration, such as going over the elements of a -collection, Rust uses higher-order functions. We'll come back to those -in a moment. +For more involved iteration, such as enumerating the elements of a +collection, Rust uses [higher-order functions](#closures). # Data structures From 1a8b00a03a45c19a47165ce037ae703e4e71f202 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 20:35:33 -0700 Subject: [PATCH 075/292] Copyedit sections 5 and 6 of the tutorial --- doc/tutorial.md | 110 ++++++++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 45 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 1695977e6277..e784a08801fb 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -702,11 +702,11 @@ collection, Rust uses [higher-order functions](#closures). Rust struct types must be declared before they are used using the `struct` syntax: `struct Name { field1: T1, field2: T2 [, ...] }`, where `T1`, `T2`, ... denote types. To construct a struct, use the same syntax, but leave off -the `struct`; for example: `Point { x: 1.0, y: 2.0 }`. +the `struct`: for example: `Point { x: 1.0, y: 2.0 }`. Structs are quite similar to C structs and are even laid out the same way in -memory (so you can read from a Rust struct in C, and vice-versa). The dot -operator is used to access struct fields (`mypoint.x`). +memory (so you can read from a Rust struct in C, and vice-versa). Use the dot +operator to access struct fields, as in `mypoint.x`. Fields that you want to mutate must be explicitly marked `mut`. @@ -720,7 +720,7 @@ struct Stack { With a value of such a type, you can do `mystack.head += 1`. If `mut` were omitted from the type, such an assignment would result in a type error. -Structs can be destructured in `match` patterns. The basic syntax is +`match` patterns destructure structs. The basic syntax is `Name {fieldname: pattern, ...}`: ~~~~ @@ -747,9 +747,9 @@ match mypoint { } ~~~ -Structs are the only type in Rust that may have user-defined destructors, -using `drop` blocks, inside of which the struct's value may be referred -to with the name `self`. +Structs are the only type in Rust that may have user-defined +destructors, defined with `drop` blocks. Inside a `drop`, the name +`self` refers to the struct's value. ~~~ struct TimeBomb { @@ -783,16 +783,16 @@ A value of this type is either a `Circle`, in which case it contains a `Point` struct and a float, or a `Rectangle`, in which case it contains two `Point` structs. The run-time representation of such a value includes an identifier of the actual form that it holds, much like the -'tagged union' pattern in C, but with better ergonomics. +'tagged union' pattern in C, but with better static guarantees. -The above declaration will define a type `Shape` that can be used to -refer to such shapes, and two functions, `Circle` and `Rectangle`, -which can be used to construct values of the type (taking arguments of -the specified types). So `Circle(Point {x: 0f, y: 0f}, 10f)` is the way to +The above declaration will define a type `Shape` that can refer to +such shapes, and two functions, `Circle` and `Rectangle`, which can be +used to construct values of the type (taking arguments of the +specified types). So `Circle(Point {x: 0f, y: 0f}, 10f)` is the way to create a new circle. -Enum variants need not have type parameters. This, for example, is -equivalent to a C enum: +Enum variants need not have type parameters. This `enum` declaration, +for example, is equivalent to a C enum: ~~~~ enum Direction { @@ -803,12 +803,12 @@ enum Direction { } ~~~~ -This will define `North`, `East`, `South`, and `West` as constants, +This declaration defines `North`, `East`, `South`, and `West` as constants, all of which have type `Direction`. -When an enum is C-like, that is, when none of the variants have -parameters, it is possible to explicitly set the discriminator values -to an integer value: +When an enum is C-like (that is, when none of the variants have +parameters), it is possible to explicitly set the discriminator values +to a constant value: ~~~~ enum Color { @@ -821,16 +821,19 @@ enum Color { If an explicit discriminator is not specified for a variant, the value defaults to the value of the previous variant plus one. If the first variant does not have a discriminator, it defaults to 0. For example, -the value of `North` is 0, `East` is 1, etc. +the value of `North` is 0, `East` is 1, `South` is 2, and `West` is 3. -When an enum is C-like the `as` cast operator can be used to get the -discriminator's value. +When an enum is C-like, you can apply the `as` cast operator to +convert it to its discriminator value as an int. -There is a special case for enums with a single variant. These are -used to define new types in such a way that the new name is not just a -synonym for an existing type, but its own distinct type. If you say: +There is a special case for enums with a single variant, which are +sometimes called "newtype-style enums" (after Haskell's "newtype" +feature). These are used to define new types in such a way that the +new name is not just a synonym for an existing type, but its own +distinct type: `type` creates a structural synonym, while this form of +`enum` creates a nominal synonym. If you say: ~~~~ enum GizmoId = int; @@ -842,7 +845,7 @@ That is a shorthand for this: enum GizmoId { GizmoId(int) } ~~~~ -Enum types like this can have their content extracted with the +You can extract the contents of such an enum type with the dereference (`*`) unary operator: ~~~~ @@ -851,6 +854,17 @@ let my_gizmo_id: GizmoId = GizmoId(10); let id_int: int = *my_gizmo_id; ~~~~ +Types like this can be useful to differentiate between data that have +the same type but must be used in different ways. + +~~~~ +enum Inches = int; +enum Centimeters = int; +~~~~ + +The above definitions allow for a simple way for programs to avoid +confusing numbers that correspond to different units. + For enum types with multiple variants, destructuring is the only way to get at their contents. All variant constructors can be used as patterns, as in this definition of `area`: @@ -866,9 +880,9 @@ fn area(sh: Shape) -> float { } ~~~~ -Like other patterns, a lone underscore ignores individual fields. -Ignoring all fields of a variant can be written `Circle(*)`. As in -their introductory form, nullary enum patterns are written without +You can write a lone `_` to ignore an individual fields, and can +ignore all fields of a variant like: `Circle(*)`. As in their +introduction form, nullary enum patterns are written without parentheses. ~~~~ @@ -887,9 +901,9 @@ fn point_from_direction(dir: Direction) -> Point { ## Tuples Tuples in Rust behave exactly like structs, except that their fields -do not have names (and can thus not be accessed with dot notation). +do not have names. Thus, you cannot access their fields with dot notation. Tuples can have any arity except for 0 or 1 (though you may consider -nil, `()`, as the empty tuple if you like). +unit, `()`, as the empty tuple if you like). ~~~~ let mytup: (int, int, float) = (10, 20, 30.0); @@ -902,10 +916,11 @@ match mytup { We've already seen several function definitions. Like all other static declarations, such as `type`, functions can be declared both at the -top level and inside other functions (or modules, which we'll come -back to [later](#modules-and-crates)). They are introduced with the -`fn` keyword, the type of arguments are specified following colons and -the return type follows the arrow. +top level and inside other functions (or in modules, which we'll come +back to [later](#modules-and-crates)). The `fn` keyword introduces a +function. A function has an argument list, which is a parenthesized +list of `expr: type` pairs separated by commas. An arrow `->` +separates the argument list and the function's return type. ~~~~ fn line(a: int, b: int, x: int) -> int { @@ -924,9 +939,12 @@ fn line(a: int, b: int, x: int) -> int { } ~~~~ -Functions that do not return a value are said to return nil, `()`, -and both the return type and the return value may be omitted from -the definition. The following two functions are equivalent. +It's better Rust style to write a return value this way instead of +writing an explicit `return`. The utility of `return` comes in when +returning early from a function. Functions that do not return a value +are said to return nil, `()`, and both the return type and the return +value may be omitted from the definition. The following two functions +are equivalent. ~~~~ fn do_nothing_the_hard_way() -> () { return (); } @@ -944,10 +962,12 @@ assert 8 == line(5, 3, 1); assert () == oops(5, 3, 1); ~~~~ -Methods are like functions, except that they are defined for a specific -'self' type (like 'this' in C++). Calling a method is done with -dot notation, as in `my_vec.len()`. Methods may be defined on most -Rust types with the `impl` keyword. As an example, lets define a draw +Methods are like functions, except that they have an implicit argument +called `self`, which has the type that the method's receiver has. The +`self` argument is like 'this' in C++. An expression with dot +notation, as in `my_vec.len()`, denotes a method +call. Implementations, written with the `impl` keyword, can define +methods on most Rust types. As an example, let's define a `draw` method on our `Shape` enum. ~~~ @@ -978,15 +998,15 @@ s.draw(); This defines an _implementation_ for `Shape` containing a single method, `draw`. In most respects the `draw` method is defined -like any other function, with the exception of the name `self`. `self` -is a special value that is automatically defined in each method, +like any other function, except for the name `self`. `self` +is a special value that is automatically in scope inside each method, referring to the value being operated on. If we wanted we could add additional methods to the same impl, or multiple impls for the same type. We'll discuss methods more in the context of [traits and generics](#generics). -> ***Note:*** The method definition syntax will change to require -> declaring the self type explicitly, as the first argument. +> ***Note:*** In the future, the method definition syntax will change to +> require declaring the `self` type explicitly, as the first argument. # The Rust memory model From 7582a482c68ab641764d39a0c3428d9b7ce39603 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 20:52:20 -0700 Subject: [PATCH 076/292] Copyedit sections 7 and 8 of the tutorial --- doc/tutorial.md | 145 +++++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 70 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index e784a08801fb..01ca36f9e9b0 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1010,22 +1010,22 @@ generics](#generics). # The Rust memory model -At this junction let's take a detour to explain the concepts involved +At this junction, let's take a detour to explain the concepts involved in Rust's memory model. We've seen some of Rust's pointer sigils (`@`, `~`, and `&`) float by in a few examples, and we aren't going to get much further without explaining them. Rust has a very particular approach to memory management that plays a significant role in shaping -the "feel" of the language. Understanding the memory landscape will -illuminate several of Rust's unique features as we encounter them. +the subjective experience of programming in the +language. Understanding the memory landscape will illuminate several +of Rust's unique features as we encounter them. Rust has three competing goals that inform its view of memory: -* Memory safety: Memory that is managed by and is accessible to the - Rust language must be guaranteed to be valid. Under normal - circumstances it must be impossible for Rust to trigger a - segmentation fault or leak memory. -* Performance: High-performance low-level code must be able to employ - a number of allocation strategies. Tracing garbage collection must be +* Memory safety: Memory that the Rust language can observe must be + guaranteed to be valid. Under normal circumstances, it must be + impossible for Rust to trigger a segmentation fault or leak memory. +* Performance: High-performance low-level code must be able to use + a number of different allocation strategies. Tracing garbage collection must be optional and, if it is not desired, memory safety must not be compromised. Less performance-critical, high-level code should be able to employ a single, garbage-collection-based, heap allocation strategy. @@ -1034,7 +1034,7 @@ Rust has three competing goals that inform its view of memory: ## How performance considerations influence the memory model -Most languages that offer strong memory safety guarantees rely upon a +Most languages that offer strong memory safety guarantees rely on a garbage-collected heap to manage all of the objects. This approach is straightforward both in concept and in implementation, but has significant costs. Languages that follow this path tend to @@ -1044,18 +1044,20 @@ boxes_: memory allocated on the heap whose lifetime is managed by the garbage collector. By comparison, languages like C++ offer very precise control over -where objects are allocated. In particular, it is common to put them +where objects are allocated. In particular, it is common to allocate them directly on the stack, avoiding expensive heap allocation. In Rust -this is possible as well, and the compiler will use a clever _pointer -lifetime analysis_ to ensure that no variable can refer to stack +this is possible as well, and the compiler uses a [clever _pointer +lifetime analysis_][borrow] to ensure that no variable can refer to stack objects after they are destroyed. +[borrow]: tutorial-borrowed-ptr.html + ## How concurrency considerations influence the memory model Memory safety in a concurrent environment involves avoiding race conditions between two threads of execution accessing the same -memory. Even high-level languages often require programmers to -correctly employ locking to ensure that a program is free of races. +memory. Even high-level languages often require programmers to make +correct use of locking to ensure that a program is free of races. Rust starts from the position that memory cannot be shared between tasks. Experience in other languages has proven that isolating each @@ -1064,28 +1066,30 @@ easy for programmers to reason about. Heap isolation has the additional benefit that garbage collection must only be done per-heap. Rust never "stops the world" to reclaim memory. -Complete isolation of heaps between tasks would, however, mean that any data -transferred between tasks must be copied. While this is a fine and -useful way to implement communication between tasks, it is also very -inefficient for large data structures. Because of this, Rust also -employs a global _exchange heap_. Objects allocated in the exchange -heap have _ownership semantics_, meaning that there is only a single -variable that refers to them. For this reason, they are referred to as -_owned boxes_. All tasks may allocate objects on the exchange heap, -then transfer ownership of those objects to other tasks, avoiding -expensive copies. +Complete isolation of heaps between tasks would, however, mean that +any data transferred between tasks must be copied. While this is a +fine and useful way to implement communication between tasks, it is +also very inefficient for large data structures. To reduce the amount +of copying, Rust also uses a global _exchange heap_. Objects allocated +in the exchange heap have _ownership semantics_, meaning that there is +only a single variable that refers to them. For this reason, they are +referred to as _owned boxes_. All tasks may allocate objects on the +exchange heap, then transfer ownership of those objects to other +tasks, avoiding expensive copies. # Boxes and pointers -In contrast to a lot of modern languages, aggregate types like structs -and enums are _not_ represented as pointers to allocated memory in -Rust. They are, as in C and C++, represented directly. This means that -if you `let x = Point {x: 1f, y: 1f};`, you are creating a struct on the -stack. If you then copy it into a data structure, the whole struct is -copied, not just a pointer. +Many modern languages have a so-called "uniform representation" for +aggregate types like structs and enums, so as to represent these types +as pointers to heap memory by default. In contrast, Rust, like C and +C++, represents such types directly. Another way to say this is that +aggregate data in Rust are *unboxed*. This means that if you `let x = +Point {x: 1f, y: 1f};`, you are creating a struct on the stack. If you +then copy it into a data structure, you copy the entire struct, not +just a pointer. For small structs like `Point`, this is usually more efficient than -allocating memory and going through a pointer. But for big structs, or +allocating memory and indirecting through a pointer. But for big structs, or those with mutable fields, it can be useful to have a single copy on the stack or on the heap, and refer to that through a pointer. @@ -1100,16 +1104,15 @@ All pointer types can be dereferenced with the `*` unary operator. > ***Note***: You may also hear managed boxes referred to as 'shared > boxes' or 'shared pointers', and owned boxes as 'unique boxes/pointers'. > Borrowed pointers are sometimes called 'region pointers'. The preferred -> terminology is as presented here. +> terminology is what we present here. ## Managed boxes -Managed boxes are pointers to heap-allocated, garbage collected memory. -Creating a managed box is done by simply applying the unary `@` -operator to an expression. The result of the expression will be boxed, -resulting in a box of the right type. Copying a shared box, as happens -during assignment, only copies a pointer, never the contents of the -box. +Managed boxes are pointers to heap-allocated, garbage collected +memory. Applying the unary `@` operator to an expression creates a +managed box. The resulting box contains the result of the +expression. Copying a shared box, as happens during assignment, only +copies a pointer, never the contents of the box. ~~~~ let x: @int = @10; // New box @@ -1119,8 +1122,8 @@ let y = x; // Copy of a pointer to the same box // then the allocation will be freed. ~~~~ -Any type that contains managed boxes or other managed types is -considered _managed_. +A _managed_ type is either of the form `@T` for some type `T`, or any +type that contains managed boxes or other managed types. ~~~ // A linked list node @@ -1148,19 +1151,19 @@ node3.prev = SomeNode(node2); Managed boxes never cross task boundaries. -> ***Note:*** managed boxes are currently reclaimed through reference -> counting and cycle collection, but we will switch to a tracing -> garbage collector eventually. +> ***Note:*** Currently, the Rust compiler generates code to reclaim +> managed boxes through reference counting and a cycle collector, but +> we will switch to a tracing garbage collector eventually. ## Owned boxes -In contrast to managed boxes, owned boxes have a single owning memory -slot and thus two owned boxes may not refer to the same memory. All -owned boxes across all tasks are allocated on a single _exchange -heap_, where their uniquely owned nature allows them to be passed -between tasks efficiently. +In contrast with managed boxes, owned boxes have a single owning +memory slot and thus two owned boxes may not refer to the same +memory. All owned boxes across all tasks are allocated on a single +_exchange heap_, where their uniquely owned nature allows tasks to +exchange them efficiently. -Because owned boxes are uniquely owned, copying them involves allocating +Because owned boxes are uniquely owned, copying them requires allocating a new owned box and duplicating the contents. Copying owned boxes is expensive so the compiler will complain if you do so without writing the word `copy`. @@ -1180,11 +1183,11 @@ let z = *x + *y; assert z == 20; ~~~~ -This is where the 'move' operator comes in. It is similar to -`copy`, but it de-initializes its source. Thus, the owned box can move -from `x` to `y`, without violating the constraint that it only has a -single owner (if you used assignment instead of the move operator, the -box would, in principle, be copied). +This is where the 'move' operator comes in. It is similar to `copy`, +but it de-initializes its source. Thus, the owned box can move from +`x` to `y`, without violating the constraint that it only has a single +owner (using assignment instead of the move operator would, in +principle, copy the box). ~~~~ {.xfail-test} let x = ~10; @@ -1198,16 +1201,16 @@ to other tasks. The sending task will give up ownership of the box, and won't be able to access it afterwards. The receiving task will become the sole owner of the box. -> ***Note:*** this discussion of copying vs moving does not account +> ***Note:*** This discussion of copying vs. moving does not account > for the "last use" rules that automatically promote copy operations -> to moves. Last use is expected to be removed from the language in +> to moves. We plan to remove last use from the language in > favor of explicit moves. ## Borrowed pointers Rust borrowed pointers are a general purpose reference/pointer type, similar to the C++ reference type, but guaranteed to point to valid -memory. In contrast to owned pointers, where the holder of a unique +memory. In contrast with owned pointers, where the holder of a unique pointer is the owner of the pointed-to memory, borrowed pointers never imply ownership. Pointers may be borrowed from any type, in which case the pointer is guaranteed not to outlive the value it points to. @@ -1220,9 +1223,9 @@ struct Point { } ~~~~ -We can use this simple definition to allocate points in many ways. For -example, in this code, each of these three local variables contains a -point, but allocated in a different place: +We can use this simple definition to allocate points in many different +ways. For example, in this code, each of these three local variables +contains a point, but allocated in a different location: ~~~ # struct Point { x: float, y: float } @@ -1306,7 +1309,8 @@ let sum = *managed + *owned + *borrowed; ~~~ Dereferenced mutable pointers may appear on the left hand side of -assignments, in which case the value they point to is modified. +assignments. Such an assignment modifies the value that the pointer +points to. ~~~ let managed = @mut 10; @@ -1321,8 +1325,8 @@ let borrowed = &mut value; ~~~ Pointers have high operator precedence, but lower precedence than the -dot operator used for field and method access. This can lead to some -awkward code filled with parenthesis. +dot operator used for field and method access. This precedence order +can sometimes make code awkward and parenthesis-filled. ~~~ # struct Point { x: float, y: float } @@ -1334,9 +1338,9 @@ let rect = &Rectangle(*start, *end); let area = (*rect).area(); ~~~ -To combat this ugliness the dot operator performs _automatic pointer -dereferencing_ on the receiver (the value on the left hand side of the -dot), so in most cases dereferencing the receiver is not necessary. +To combat this ugliness the dot operator applies _automatic pointer +dereferencing_ to the receiver (the value on the left hand side of the +dot), so in most cases, explicitly dereferencing the receiver is not necessary. ~~~ # struct Point { x: float, y: float } @@ -1348,8 +1352,9 @@ let rect = &Rectangle(*start, *end); let area = rect.area(); ~~~ -Auto-dereferencing is performed through any number of pointers. If you -felt inclined you could write something silly like +You can write an expression that dereferences any number of pointers +automatically. For example, if you felt inclined, you could write +something silly like ~~~ # struct Point { x: float, y: float } @@ -1357,7 +1362,7 @@ let point = &@~Point { x: 10f, y: 20f }; io::println(fmt!("%f", point.x)); ~~~ -The indexing operator (`[]`) is also auto-dereferencing. +The indexing operator (`[]`) also auto-dereferences. # Vectors and strings From 6d250517edc9823b39f6e239ec03d19a18b577bd Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 21:06:22 -0700 Subject: [PATCH 077/292] Copyedit sections 9 and 10 of the tutorial --- doc/tutorial.md | 93 +++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 01ca36f9e9b0..1103ba112a2e 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1366,7 +1366,7 @@ The indexing operator (`[]`) also auto-dereferences. # Vectors and strings -Vectors are a contiguous section of memory containing zero or more +A vector is a contiguous section of memory containing zero or more values of the same type. Like other types in Rust, vectors can be stored on the stack, the local heap, or the exchange heap. Borrowed pointers to vectors are also called 'slices'. @@ -1411,10 +1411,10 @@ my_crayons += your_crayons; > ***Note:*** The above examples of vector addition use owned > vectors. Some operations on slices and stack vectors are -> not well supported yet, owned vectors are often the most +> not yet well-supported. Owned vectors are often the most > usable. -Indexing into vectors is done with square brackets: +Square brackets denote indexing into a vector: ~~~~ # enum Crayon { Almond, AntiqueBrass, Apricot, @@ -1429,7 +1429,7 @@ match crayons[0] { ~~~~ The elements of a vector _inherit the mutability of the vector_, -and as such individual elements may not be reassigned when the +and as such, individual elements may not be reassigned when the vector lives in an immutable slot. ~~~ {.xfail-test} @@ -1459,13 +1459,13 @@ mutable_crayons[0] = Apricot; This is a simple example of Rust's _dual-mode data structures_, also referred to as _freezing and thawing_. -Strings are implemented with vectors of `u8`, though they have a distinct -type. They support most of the same allocation options as -vectors, though the string literal without a storage sigil, e.g. -`"foo"` is treated differently than a comparable vector (`[foo]`). -Whereas plain vectors are stack-allocated fixed-length vectors, -plain strings are region pointers to read-only memory. Strings -are always immutable. +Strings are implemented with vectors of `u8`, though they have a +distinct type. They support most of the same allocation options as +vectors, though the string literal without a storage sigil (for +example, `"foo"`) is treated differently than a comparable vector +(`[foo]`). Whereas plain vectors are stack-allocated fixed-length +vectors, plain strings are region pointers to read-only +memory. All strings are immutable. ~~~ // A plain string is a slice to read-only (static) memory @@ -1528,8 +1528,9 @@ if favorite_crayon_name.len() > 5 { # Closures Named functions, like those we've seen so far, may not refer to local -variables declared outside the function - they do not "close over -their environment". For example, you couldn't write the following: +variables declared outside the function: they do not close over their +environment (sometimes referred to as "capturing" variables in their +environment). For example, you couldn't write the following: ~~~~ {.ignore} let foo = 10; @@ -1552,10 +1553,10 @@ let closure = |arg| println(fmt!("captured_var=%d, arg=%d", captured_var, arg)); call_closure_with_ten(closure); ~~~~ -Closures begin with the argument list between bars and are followed by +Closures begin with the argument list between vertical bars and are followed by a single expression. The types of the arguments are generally omitted, as is the return type, because the compiler can almost always infer -them. In the rare case where the compiler needs assistance though, the +them. In the rare case where the compiler needs assistance, though, the arguments and return types may be annotated. ~~~~ @@ -1575,9 +1576,10 @@ let mut max = 0; Stack closures are very efficient because their environment is allocated on the call stack and refers by pointer to captured locals. To ensure that stack closures never outlive the local -variables to which they refer, they can only be used in argument -position and cannot be stored in structures nor returned from -functions. Despite the limitations stack closures are used +variables to which they refer, stack closures are not +first-class. That is, they can only be used in argument position; they +cannot be stored in data structures or returned from +functions. Despite these limitations, stack closures are used pervasively in Rust code. ## Managed closures @@ -1586,12 +1588,12 @@ When you need to store a closure in a data structure, a stack closure will not do, since the compiler will refuse to let you store it. For this purpose, Rust provides a type of closure that has an arbitrary lifetime, written `fn@` (boxed closure, analogous to the `@` pointer -type described earlier). +type described earlier). This type of closure *is* first-class. A managed closure does not directly access its environment, but merely copies out the values that it closes over into a private data structure. This means that it can not assign to these variables, and -will not 'see' updates to them. +cannot observe updates to them. This code creates a closure that adds a given string to its argument, returns it from a function, and then calls it: @@ -1608,12 +1610,12 @@ fn main() { } ~~~~ -This example uses the long closure syntax, `fn@(s: ~str) ...`, -making the fact that we are declaring a box closure explicit. In -practice boxed closures are usually defined with the short closure -syntax introduced earlier, in which case the compiler will infer -the type of closure. Thus our managed closure example could also -be written: +This example uses the long closure syntax, `fn@(s: ~str) ...`. Using +this syntax makes it explicit that we are declaring a boxed +closure. In practice, boxed closures are usually defined with the +short closure syntax introduced earlier, in which case the compiler +infers the type of closure. Thus our managed closure example could +also be written: ~~~~ fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str { @@ -1626,18 +1628,18 @@ fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str { Owned closures, written `fn~` in analogy to the `~` pointer type, hold on to things that can safely be sent between processes. They copy the values they close over, much like managed -closures, but they also 'own' them—meaning no other code can access +closures, but they also own them: that is, no other code can access them. Owned closures are used in concurrent code, particularly for spawning [tasks](#tasks). ## Closure compatibility -A nice property of Rust closures is that you can pass any kind of +Rust closures have a convenient subtyping property: you can pass any kind of closure (as long as the arguments and return types match) to functions that expect a `fn()`. Thus, when writing a higher-order function that -wants to do nothing with its function argument beyond calling it, you -should almost always specify the type of that argument as `fn()`, so -that callers have the flexibility to pass whatever they want. +only calls its function argument, and does nothing else with it, you +should almost always declare the type of that argument as `fn()`. That way, +callers may pass any kind of closure. ~~~~ fn call_twice(f: fn()) { f(); f(); } @@ -1650,7 +1652,7 @@ call_twice(bare_function); ~~~~ > ***Note:*** Both the syntax and the semantics will be changing -> in small ways. At the moment they can be unsound in multiple +> in small ways. At the moment they can be unsound in some > scenarios, particularly with non-copyable types. ## Do syntax @@ -1658,7 +1660,7 @@ call_twice(bare_function); The `do` expression provides a way to treat higher-order functions (functions that take closures as arguments) as control structures. -Consider this function which iterates over a vector of +Consider this function that iterates over a vector of integers, passing in a pointer to each integer in the vector: ~~~~ @@ -1702,13 +1704,14 @@ do each(&[1, 2, 3]) |n| { ~~~~ The call is prefixed with the keyword `do` and, instead of writing the -final closure inside the argument list it is moved outside of the -parenthesis where it looks visually more like a typical block of +final closure inside the argument list, it appears outside of the +parentheses, where it looks more like a typical block of code. -`do` is often used to create tasks with the `task::spawn` function. -`spawn` has the signature `spawn(fn: fn~())`. In other words, it -is a function that takes an owned closure that takes no arguments. +`do` is a convenient way to create tasks with the `task::spawn` +function. `spawn` has the signature `spawn(fn: fn~())`. In other +words, it is a function that takes an owned closure that takes no +arguments. ~~~~ use task::spawn; @@ -1731,10 +1734,10 @@ do spawn { ## For loops -Most iteration in Rust is done with `for` loops. Like `do`, -`for` is a nice syntax for doing control flow with closures. -Additionally, within a `for` loop, `break`, `loop`, and `return` -work just as they do with `while` and `loop`. +The most common way to express iteration in Rust is with a `for` +loop. Like `do`, `for` is a nice syntax for describing control flow +with closures. Additionally, within a `for` loop, `break`, `loop`, +and `return` work just as they do with `while` and `loop`. Consider again our `each` function, this time improved to break early when the iteratee returns `false`: @@ -1765,7 +1768,7 @@ each(&[2, 4, 8, 5, 16], |n| { ~~~~ With `for`, functions like `each` can be treated more -like builtin looping structures. When calling `each` +like built-in looping structures. When calling `each` in a `for` loop, instead of returning `false` to break out of the loop, you just write `break`. To skip ahead to the next iteration, write `loop`. @@ -1783,8 +1786,8 @@ for each(&[2, 4, 8, 5, 16]) |n| { As an added bonus, you can use the `return` keyword, which is not normally allowed in closures, in a block that appears as the body of a -`for` loop — this will cause a return to happen from the outer -function, not just the loop body. +`for` loop: the meaning of `return` in such a block is to return from +the enclosing function, not just the loop body. ~~~~ # use each = vec::each; From 39acb06503bc387709b22c17c32cd58cd16b617a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 10 Oct 2012 21:29:25 -0700 Subject: [PATCH 078/292] Copyedit sections 11-13 of the tutorial. That's all, folks! --- doc/tutorial.md | 186 ++++++++++++++++++++++++++---------------------- 1 file changed, 102 insertions(+), 84 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 1103ba112a2e..ae88cda8d8e9 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1807,10 +1807,13 @@ fn contains(v: &[int], elt: int) -> bool { # Generics -Throughout this tutorial, we've been defining functions that act only on -specific data types. With type parameters we can also define functions whose -arguments represent generic types, and which can be invoked with a variety -of types. Consider a generic `map` function. +Throughout this tutorial, we've been defining functions that act only +on specific data types. With type parameters we can also define +functions whose arguments have generic types, and which can be invoked +with a variety of types. Consider a generic `map` function, which +takes a function `function` and a vector `vector` and returns a new +vector consisting of the result of applying `function` to each element +of `vector`: ~~~~ fn map(vector: &[T], function: fn(v: &T) -> U) -> ~[U] { @@ -1824,17 +1827,18 @@ fn map(vector: &[T], function: fn(v: &T) -> U) -> ~[U] { When defined with type parameters, as denoted by ``, this function can be applied to any type of vector, as long as the type of -`function`'s argument and the type of the vector's content agree with +`function`'s argument and the type of the vector's contents agree with each other. Inside a generic function, the names of the type parameters -(capitalized by convention) stand for opaque types. You can't look -inside them, but you can pass them around. Note that instances of -generic types are often passed by pointer. For example, the -parameter `function()` is supplied with a pointer to a value of type -`T` and not a value of type `T` itself. This ensures that the -function works with the broadest set of types possible, since some -types are expensive or illegal to copy and pass by value. +(capitalized by convention) stand for opaque types. All you can do +with instances of these types is pass them around: you can't apply any +operations to them or pattern-match on them. Note that instances of +generic types are often passed by pointer. For example, the parameter +`function()` is supplied with a pointer to a value of type `T` and not +a value of type `T` itself. This ensures that the function works with +the broadest set of types possible, since some types are expensive or +illegal to copy and pass by value. Generic `type`, `struct`, and `enum` declarations follow the same pattern: @@ -1852,15 +1856,16 @@ enum Maybe { } ~~~~ -These declarations produce valid types like `Set`, `Stack` -and `Maybe`. +These declarations can be instantiated to valid types like `Set`, +`Stack` and `Maybe`. -Generic functions in Rust are compiled to very efficient runtime code -through a process called _monomorphisation_. This is a fancy way of -saying that, for each generic function you call, the compiler -generates a specialized version that is optimized specifically for the -argument types. In this respect Rust's generics have similar -performance characteristics to C++ templates. +The Rust compiler compiles generic functions very efficiently by +*monomorphizing* them. *Monomorphization* is a fancy name for a simple +idea: generate a separate copy of each generic function at each call +site where it is called, a copy that is specialized to the argument +types and can thus be optimized specifically for them. In this +respect, Rust's generics have similar performance characteristics to +C++ templates. ## Traits @@ -1869,15 +1874,19 @@ are very limited. After all, since the function doesn't know what types it is operating on, it can't safely modify or query their values. This is where _traits_ come into play. Traits are Rust's most powerful tool for writing polymorphic code. Java developers will see -in them aspects of Java interfaces, and Haskellers will notice their -similarities to type classes. +them as similar to Java interfaces, and Haskellers will notice their +similarities to type classes. Rust's traits are a form of *bounded +polymorphism*: a trait is a way of limiting the set of possible types +that a type parameter could refer to. -As motivation, let us consider copying in Rust. Perhaps surprisingly, -the copy operation is not defined for all Rust types. In -particular, types with user-defined destructors cannot be copied, -either implicitly or explicitly, and neither can types that own other -types containing destructors (the actual mechanism for defining -destructors will be discussed elsewhere). +As motivation, let us consider copying in Rust. The `copy` operation +is not defined for all Rust types. One reason is user-defined +destructors: copying a type that has a destructor could result in the +destructor running multiple times. Therefore, types with user-defined +destructors cannot be copied, either implicitly or explicitly, and +neither can types that own other types containing destructors (see the +section on [structs](#structs) for the actual mechanism for defining +destructors). This complicates handling of generic functions. If you have a type parameter `T`, can you copy values of that type? In Rust, you can't, @@ -1890,8 +1899,8 @@ fn head_bad(v: &[T]) -> T { } ~~~~ -We can tell the compiler though that the `head` function is only for -copyable types with the `Copy` trait. +However, we can tell the compiler that the `head` function is only for +copyable types: that is, those that have the `Copy` trait. ~~~~ // This does @@ -1903,14 +1912,17 @@ fn head(v: &[T]) -> T { This says that we can call `head` on any type `T` as long as that type implements the `Copy` trait. When instantiating a generic function, you can only instantiate it with types that implement the correct -trait, so you could not apply `head` to a type with a destructor. +trait, so you could not apply `head` to a type with a +destructor. (`Copy` is a special trait that is built in to the +compiler, making it possible for the compiler to enforce this +restriction.) While most traits can be defined and implemented by user code, three traits are automatically derived and implemented for all applicable types by the compiler, and may not be overridden: -* `Copy` - Types that can be copied, either implicitly, or using the - `copy` expression. All types are copyable unless they are classes +* `Copy` - Types that can be copied: either implicitly, or explicitly with the + `copy` operator. All types are copyable unless they are classes with destructors or otherwise contain classes with destructors. * `Send` - Sendable (owned) types. All types are sendable unless they @@ -1957,7 +1969,7 @@ impl ~str: Printable { # (~"foo").print(); ~~~~ -Methods defined in an implementation of a trait may be called just as +Methods defined in an implementation of a trait may be called just like any other method, using dot notation, as in `1.print()`. Traits may themselves contain type parameters. A trait for generalized sequence types might look like the following: @@ -1979,14 +1991,14 @@ impl ~[T]: Seq { The implementation has to explicitly declare the type parameter that it binds, `T`, before using it to specify its trait type. Rust requires this declaration because the `impl` could also, for example, -specify an implementation of `Seq`. The trait type -- appearing -after the colon in the `impl` -- *refers* to a type, rather than +specify an implementation of `Seq`. The trait type (appearing +after the colon in the `impl`) *refers* to a type, rather than defining one. The type parameters bound by a trait are in scope in each of the method declarations. So, re-declaring the type parameter -`T` as an explicit type parameter for `len` -- in either the trait or -the impl -- would be a compile-time error. +`T` as an explicit type parameter for `len`, in either the trait or +the impl, would be a compile-time error. Within a trait definition, `self` is a special type that you can think of as a type parameter. An implementation of the trait for any given @@ -2006,16 +2018,17 @@ impl int: Eq { } ~~~~ -Notice that in the trait definition, `equals` takes a `self` type -argument, whereas, in the impl, `equals` takes an `int` type argument, -and uses `self` as the name of the receiver (analogous to the `this` pointer -in C++). +Notice that in the trait definition, `equals` takes a parameter of +type `self`. In contrast, in the `impl`, `equals` takes a parameter of +type `int`, and uses `self` as the name of the receiver (analogous to +the `this` pointer in C++). ## Bounded type parameters and static method dispatch -Traits give us a language for talking about the abstract capabilities -of types, and we can use this to place _bounds_ on type parameters, -so that we can then operate on generic types. +Traits give us a language for defining predicates on types, or +abstract properties that types can have. We can use this language to +define _bounds_ on type parameters, so that we can then operate on +generic types. ~~~~ # trait Printable { fn print(); } @@ -2026,14 +2039,14 @@ fn print_all(printable_things: ~[T]) { } ~~~~ -By declaring `T` as conforming to the `Printable` trait (as we earlier -did with `Copy`), it becomes possible to call methods from that trait -on values of that type inside the function. It will also cause a +Declaring `T` as conforming to the `Printable` trait (as we earlier +did with `Copy`) makes it possible to call methods from that trait +on values of type `T` inside the function. It will also cause a compile-time error when anyone tries to call `print_all` on an array whose element type does not have a `Printable` implementation. Type parameters can have multiple bounds by separating them with spaces, -as in this version of `print_all` that makes copies of elements. +as in this version of `print_all` that copies elements. ~~~ # trait Printable { fn print(); } @@ -2083,10 +2096,10 @@ fn draw_all(shapes: &[@Drawable]) { } ~~~~ -In this example there is no type parameter. Instead, the `@Drawable` -type is used to refer to any managed box value that implements the -`Drawable` trait. To construct such a value, you use the `as` operator -to cast a value to a trait type: +In this example, there is no type parameter. Instead, the `@Drawable` +type denotes any managed box value that implements the `Drawable` +trait. To construct such a value, you use the `as` operator to cast a +value to a trait type: ~~~~ # type Circle = int; type Rectangle = bool; @@ -2104,10 +2117,12 @@ let r: @Rectangle = @new_rectangle(); draw_all(&[c as @Drawable, r as @Drawable]); ~~~~ -Note that, like strings and vectors, trait types have dynamic size -and may only be used via one of the pointer types. In turn, the -`impl` is defined for `@Circle` and `@Rectangle` instead of for -just `Circle` and `Rectangle`. Other pointer types work as well. +We omit the code for `new_circle` and `new_rectangle`; imagine that +these just return `Circle`s and `Rectangle`s with a default size. Note +that, like strings and vectors, trait types have dynamic size and may +only be referred to via one of the pointer types. That's why the `impl` is +defined for `@Circle` and `@Rectangle` instead of for just `Circle` +and `Rectangle`. Other pointer types work as well. ~~~{.xfail-test} # type Circle = int; type Rectangle = int; @@ -2123,13 +2138,13 @@ let owny: ~Drawable = ~new_circle() as ~Drawable; let stacky: &Drawable = &new_circle() as &Drawable; ~~~ -> ***Note:*** Other pointer types actually _do not_ work here. This is +> ***Note:*** Other pointer types actually _do not_ work here yet. This is > an evolving corner of the language. Method calls to trait types are _dynamically dispatched_. Since the compiler doesn't know specifically which functions to call at compile -time it uses a lookup table (vtable) to decide at runtime which -method to call. +time it uses a lookup table (also known as a vtable or dictionary) to +select the method to call at runtime. This usage of traits is similar to Java interfaces. @@ -2170,17 +2185,18 @@ fn chicken_farmer() { ~~~ These farm animal functions have a new keyword, `pub`, attached to -them. This is a visibility modifier that allows item to be accessed -outside of the module in which they are declared, using `::`, as in -`farm::chicken`. Items, like `fn`, `struct`, etc. are private by -default. +them. The `pub` keyword modifies an item's visibility, making it +visible outside its containing module. An expression with `::`, like +`farm::chicken`, can name an item outside of its containing +module. Items, such as those declared with `fn`, `struct`, `enum`, +`type`, or `const`, are module-private by default. Visibility restrictions in Rust exist only at module boundaries. This -is quite different from most object-oriented languages that also enforce -restrictions on objects themselves. That's not to say that Rust doesn't -support encapsulation - both struct fields and methods can be private - -but it is at the module level, not the class level. Note that fields -and methods are _public_ by default. +is quite different from most object-oriented languages that also +enforce restrictions on objects themselves. That's not to say that +Rust doesn't support encapsulation: both struct fields and methods can +be private. But this encapsulation is at the module level, not the +struct level. Note that fields and methods are _public_ by default. ~~~ mod farm { @@ -2220,7 +2236,7 @@ fn main() { ## Crates -The unit of independent compilation in Rust is the crate - rustc +The unit of independent compilation in Rust is the crate: rustc compiles a single crate at a time, from which it produces either a library or executable. @@ -2294,22 +2310,24 @@ fn main() { bar::baz(); } ## Using other crates -Having compiled a crate into a library you can use it in another crate -with an `extern mod` directive. `extern mod` can appear at the top of -a crate file or at the top of modules. It will cause the compiler to -look in the library search path (which you can extend with `-L` -switch) for a compiled Rust library with the right name, then add a -module with that crate's name into the local scope. +The `extern mod` directive lets you use a crate (once it's been +compiled into a library) from inside another crate. `extern mod` can +appear at the top of a crate file or at the top of modules. It will +cause the compiler to look in the library search path (which you can +extend with the `-L` switch) for a compiled Rust library with the +right name, then add a module with that crate's name into the local +scope. For example, `extern mod std` links the [standard library]. [standard library]: std/index.html -When a comma-separated list of name/value pairs is given after `extern -mod`, these are matched against the attributes provided in the `link` -attribute of the crate file, and a crate is only used when the two -match. A `name` value can be given to override the name used to search -for the crate. +When a comma-separated list of name/value pairs appears after `extern +mod`, the compiler front-end matches these pairs against the +attributes provided in the `link` attribute of the crate file. The +front-end will only select this crate for use if the actual pairs +match the declared attributes. You can provide a `name` value to +override the name used to search for the crate. Our example crate declared this set of `link` attributes: @@ -2317,7 +2335,7 @@ Our example crate declared this set of `link` attributes: #[link(name = "farm", vers = "2.5", author = "mjh")]; ~~~~ -Which can then be linked with any (or all) of the following: +Which you can then link with any (or all) of the following: ~~~~ {.xfail-test} extern mod farm; @@ -2325,7 +2343,7 @@ extern mod my_farm (name = "farm", vers = "2.5"); extern mod my_auxiliary_farm (name = "farm", author = "mjh"); ~~~~ -If any of the requested metadata does not match then the crate +If any of the requested metadata do not match, then the crate will not be compiled successfully. ## A minimal example @@ -2361,7 +2379,7 @@ a hash representing the crate metadata. ## The core library -The Rust [core] library acts as the language runtime and contains +The Rust [core] library is the language runtime and contains required memory management and task scheduling code as well as a number of modules necessary for effective usage of the primitive types. Methods on [vectors] and [strings], implementations of most From 97ecde297e2b49fc6445c233cb95d8cd1c341b2d Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Mon, 8 Oct 2012 21:40:09 +0200 Subject: [PATCH 079/292] Conditional usage of LLVM DebugFlag DebugFlag is conditionally exported by LLVM in llvm/Support/Debug.h in-between an #ifndef NDEBUG block; RustWrapper should not unconditionally use it. This closes #3701. Signed-off-by: Luca Bruno --- src/rustllvm/RustWrapper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index fc2049507eed..498a4e137f0e 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -493,5 +493,7 @@ extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, } extern "C" void LLVMSetDebug(int Enabled) { +#ifndef NDEBUG DebugFlag = Enabled; +#endif } From 012bb7de5ba65bfd7b3483595e65a4cda1d1f682 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 10:23:24 -0700 Subject: [PATCH 080/292] Typo: an -> a. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 9d2e12fde845..a3ef24ab8dd0 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -825,7 +825,7 @@ path_glob : ident [ "::" path_glob ] ? ~~~~~~~~ A _use declaration_ creates one or more local name bindings synonymous -with some other [path](#paths). Usually an use declaration is used to +with some other [path](#paths). Usually a `use` declaration is used to shorten the path required to refer to a module item. *Note*: unlike many languages, Rust's `use` declarations do *not* declare From 860573e3e00b5a807021b8c7a94a9672de4fa687 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 10:31:57 -0700 Subject: [PATCH 081/292] Reword para on diverging functions. --- doc/rust.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index a3ef24ab8dd0..8846ac9f9453 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -936,11 +936,13 @@ fn f(i: int) -> int { } ~~~~ -The typechecker would complain that `f` doesn't return a value in the -`else` branch. Adding the `!` annotation on `my_err` would -express that `f` requires no explicit `return`, as if it returns -control to the caller, it returns a value (true because it never returns -control). +This will not compile without the `!` annotation on `my_err`, +since the `else` branch of the conditional in `f` does not return an `int`, +as required by the signature of `f`. +Adding the `!` annotation to `my_err` informs the typechecker that, +should control ever enter `my_err`, no further type judgments about `f` need to hold, +since control will never resume in any context that relies on those judgments. +Thus the return type on `f` only needs to reflect the `if` branch of the conditional. #### Pure functions From c9cee7c2af5f3d2de06203d697b3890320a3dfc6 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 10:33:32 -0700 Subject: [PATCH 082/292] Reorder function sections. --- doc/rust.md | 174 +++++++++++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 85 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 8846ac9f9453..9048b436911f 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -898,51 +898,69 @@ fn add(x: int, y: int) -> int { } ~~~~ -#### Diverging functions -A special kind of function can be declared with a `!` character where the -output slot type would normally be. For example: +#### Generic functions -~~~~ -fn my_err(s: ~str) -> ! { - log(info, s); - fail; +A _generic function_ allows one or more _parameterized types_ to +appear in its signature. Each type parameter must be explicitly +declared, in an angle-bracket-enclosed, comma-separated list following +the function name. + +~~~~ {.xfail-test} +fn iter(seq: ~[T], f: fn(T)) { + for seq.each |elt| { f(elt); } +} +fn map(seq: ~[T], f: fn(T) -> U) -> ~[U] { + let mut acc = ~[]; + for seq.each |elt| { acc.push(f(elt)); } + acc } ~~~~ -We call such functions "diverging" because they never return a value to the -caller. Every control path in a diverging function must end with a -[`fail`](#fail-expressions) or a call to another diverging function on every -control path. The `!` annotation does *not* denote a type. Rather, the result -type of a diverging function is a special type called $\bot$ ("bottom") that -unifies with any type. Rust has no syntax for $\bot$. +Inside the function signature and body, the name of the type parameter +can be used as a type name. -It might be necessary to declare a diverging function because as mentioned -previously, the typechecker checks that every control path in a function ends -with a [`return`](#return-expressions) or diverging expression. So, if `my_err` -were declared without the `!` annotation, the following code would not -typecheck: +When a generic function is referenced, its type is instantiated based +on the context of the reference. For example, calling the `iter` +function defined above on `[1, 2]` will instantiate type parameter `T` +with `int`, and require the closure parameter to have type +`fn(int)`. + +Since a parameter type is opaque to the generic function, the set of +operations that can be performed on it is limited. Values of parameter +type can always be moved, but they can only be copied when the +parameter is given a [`copy` bound](#type-kinds). ~~~~ -# fn my_err(s: ~str) -> ! { fail } - -fn f(i: int) -> int { - if i == 42 { - return 42; - } - else { - my_err(~"Bad number!"); - } -} +fn id(x: T) -> T { x } ~~~~ -This will not compile without the `!` annotation on `my_err`, -since the `else` branch of the conditional in `f` does not return an `int`, -as required by the signature of `f`. -Adding the `!` annotation to `my_err` informs the typechecker that, -should control ever enter `my_err`, no further type judgments about `f` need to hold, -since control will never resume in any context that relies on those judgments. -Thus the return type on `f` only needs to reflect the `if` branch of the conditional. +Similarly, [trait](#traits) bounds can be specified for type +parameters to allow methods with that trait to be called on values +of that type. + + +#### Unsafe functions + +Unsafe functions are those containing unsafe operations that are not contained in an [`unsafe` block](#unsafe-blocks). + +Unsafe operations are those that potentially violate the memory-safety guarantees of Rust's static semantics. +Specifically, the following operations are considered unsafe: + + - Dereferencing a [raw pointer](#pointer-types) + - Casting a [raw pointer](#pointer-types) to a safe pointer type + - Breaking the [purity-checking rules](#pure-functions) + - Calling an unsafe function + +##### Unsafe blocks + +A block of code can also be prefixed with the `unsafe` keyword, +to permit a sequence of unsafe operations in an otherwise-safe function. +This facility exists because the static semantics of a Rust are a necessary approximation of the dynamic semantics. +When a programmer has sufficient conviction that a sequence of unsafe operations is actually safe, +they can encapsulate that sequence (taken as a whole) within an `unsafe` block. +The compiler will consider uses of such code "safe", to the surrounding context. + #### Pure functions @@ -1003,66 +1021,52 @@ function. So, to use `foldl` in a pure list length function that a pure function could then use, we must use an `unsafe` block wrapped around the call to `pure_foldl` in the definition of `pure_length`. -#### Generic functions -A _generic function_ allows one or more _parameterized types_ to -appear in its signature. Each type parameter must be explicitly -declared, in an angle-bracket-enclosed, comma-separated list following -the function name. +#### Diverging functions -~~~~ {.xfail-test} -fn iter(seq: ~[T], f: fn(T)) { - for seq.each |elt| { f(elt); } -} -fn map(seq: ~[T], f: fn(T) -> U) -> ~[U] { - let mut acc = ~[]; - for seq.each |elt| { acc.push(f(elt)); } - acc +A special kind of function can be declared with a `!` character where the +output slot type would normally be. For example: + +~~~~ +fn my_err(s: ~str) -> ! { + log(info, s); + fail; } ~~~~ -Inside the function signature and body, the name of the type parameter -can be used as a type name. +We call such functions "diverging" because they never return a value to the +caller. Every control path in a diverging function must end with a +[`fail`](#fail-expressions) or a call to another diverging function on every +control path. The `!` annotation does *not* denote a type. Rather, the result +type of a diverging function is a special type called $\bot$ ("bottom") that +unifies with any type. Rust has no syntax for $\bot$. -When a generic function is referenced, its type is instantiated based -on the context of the reference. For example, calling the `iter` -function defined above on `[1, 2]` will instantiate type parameter `T` -with `int`, and require the closure parameter to have type -`fn(int)`. - -Since a parameter type is opaque to the generic function, the set of -operations that can be performed on it is limited. Values of parameter -type can always be moved, but they can only be copied when the -parameter is given a [`copy` bound](#type-kinds). +It might be necessary to declare a diverging function because as mentioned +previously, the typechecker checks that every control path in a function ends +with a [`return`](#return-expressions) or diverging expression. So, if `my_err` +were declared without the `!` annotation, the following code would not +typecheck: ~~~~ -fn id(x: T) -> T { x } +# fn my_err(s: ~str) -> ! { fail } + +fn f(i: int) -> int { + if i == 42 { + return 42; + } + else { + my_err(~"Bad number!"); + } +} ~~~~ -Similarly, [trait](#traits) bounds can be specified for type -parameters to allow methods with that trait to be called on values -of that type. - -#### Unsafe functions - -Unsafe functions are those containing unsafe operations that are not contained in an [`unsafe` block](#unsafe-blocks). - -Unsafe operations are those that potentially violate the memory-safety guarantees of Rust's static semantics. -Specifically, the following operations are considered unsafe: - - - Dereferencing a [raw pointer](#pointer-types) - - Casting a [raw pointer](#pointer-types) to a safe pointer type - - Breaking the [purity-checking rules](#pure-functions) - - Calling an unsafe function - -##### Unsafe blocks - -A block of code can also be prefixed with the `unsafe` keyword, -to permit a sequence of unsafe operations in an otherwise-safe function. -This facility exists because the static semantics of a Rust are a necessary approximation of the dynamic semantics. -When a programmer has sufficient conviction that a sequence of unsafe operations is actually safe, -they can encapsulate that sequence (taken as a whole) within an `unsafe` block. -The compiler will consider uses of such code "safe", to the surrounding context. +This will not compile without the `!` annotation on `my_err`, +since the `else` branch of the conditional in `f` does not return an `int`, +as required by the signature of `f`. +Adding the `!` annotation to `my_err` informs the typechecker that, +should control ever enter `my_err`, no further type judgments about `f` need to hold, +since control will never resume in any context that relies on those judgments. +Thus the return type on `f` only needs to reflect the `if` branch of the conditional. #### Extern functions From a2cace473b8f375c36e7f977867c11852c949527 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 10:36:37 -0700 Subject: [PATCH 083/292] manual: remove a mode. --- doc/rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 9048b436911f..5707602ec9b8 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1000,7 +1000,7 @@ An example of a pure function that uses an unsafe block: ~~~~ {.xfail-test} # use std::list::*; -fn pure_foldl(ls: List, u: U, f: fn(&&T, &&U) -> U) -> U { +fn pure_foldl(ls: List, u: U, f: fn(&T, &U) -> U) -> U { match ls { Nil => u, Cons(hd, tl) => f(hd, pure_foldl(*tl, f(hd, u), f)) @@ -1008,7 +1008,7 @@ fn pure_foldl(ls: List, u: U, f: fn(&&T, &&U) -> U) -> U { } pure fn pure_length(ls: List) -> uint { - fn count(_t: T, &&u: uint) -> uint { u + 1u } + fn count(_t: &T, u: &uint) -> uint { *u + 1u } unsafe { pure_foldl(ls, 0u, count) } From 9e6df2827721aa2ddba33a409cdda109b33cf232 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 10:38:07 -0700 Subject: [PATCH 084/292] manual: capitalize 'Copy'. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 5707602ec9b8..a4bbcc14a089 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -929,7 +929,7 @@ with `int`, and require the closure parameter to have type Since a parameter type is opaque to the generic function, the set of operations that can be performed on it is limited. Values of parameter type can always be moved, but they can only be copied when the -parameter is given a [`copy` bound](#type-kinds). +parameter is given a [`Copy` bound](#type-kinds). ~~~~ fn id(x: T) -> T { x } From bc68a88593a5f5b0cd33c5c9e8e83a1581fe6b12 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 10:41:24 -0700 Subject: [PATCH 085/292] manual: improve description of unsafe functions. --- doc/rust.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index a4bbcc14a089..8d2944def5b2 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -943,14 +943,15 @@ of that type. #### Unsafe functions Unsafe functions are those containing unsafe operations that are not contained in an [`unsafe` block](#unsafe-blocks). +Such a function must be prefixed with the keyword `unsafe`. Unsafe operations are those that potentially violate the memory-safety guarantees of Rust's static semantics. Specifically, the following operations are considered unsafe: - - Dereferencing a [raw pointer](#pointer-types) - - Casting a [raw pointer](#pointer-types) to a safe pointer type - - Breaking the [purity-checking rules](#pure-functions) - - Calling an unsafe function + - Dereferencing a [raw pointer](#pointer-types). + - Casting a [raw pointer](#pointer-types) to a safe pointer type. + - Breaking the [purity-checking rules](#pure-functions) in a `pure` function. + - Calling an unsafe function. ##### Unsafe blocks From dfd00ec8a8f15062a4bf973847332e246e9851f5 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 10:42:46 -0700 Subject: [PATCH 086/292] manual: link to kinds, remove kind-list. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 8d2944def5b2..cde00aa2364b 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1104,7 +1104,7 @@ specific type; the type-specified aspects of a value include: * Whether the value represents textual or numerical information. * Whether the value represents integral or floating-point information. * The sequence of memory operations required to access the value. -* The *kind* of the type (pinned, unique or shared). +* The [kind](#type-kinds) of the type. For example, the type `{x: u8, y: u8`} defines the set of immutable values that are composite records, each containing two unsigned 8-bit integers From 0673b49b05f2de2a67dd81a27a2af4eeb0ccc830 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 10:43:18 -0700 Subject: [PATCH 087/292] manual: remove mention of tags, now very obsolete. --- doc/rust.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index cde00aa2364b..42b6143c46f6 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1116,9 +1116,7 @@ accessed through the components `x` and `y`, and laid out in memory with the An _enumeration item_ simultaneously declares a new nominal [enumerated type](#enumerated-types) as well as a set of *constructors* that can be used to create or pattern-match values of the corresponding enumerated -type. Note that `enum` previously was referred to as a `tag`, however this -definition has been deprecated. While `tag` is no longer used, the two are -synonymous. +type. The constructors of an `enum` type may be recursive: that is, each constructor may take an argument that refers, directly or indirectly, to the enumerated From 9cba4af24366b6c08299e709fac26361d7920ccb Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 11:47:27 -0700 Subject: [PATCH 088/292] manual: describe structs, split out handling of recursion from enums, deprecate records. --- doc/rust.md | 163 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 102 insertions(+), 61 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 42b6143c46f6..5f5cde72cf97 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -705,6 +705,7 @@ There are several kinds of item: * [modules](#modules) * [functions](#functions) * [type definitions](#type-definitions) + * [structures](#structures) * [enumerations](#enumerations) * [constants](#constants) * [traits](#traits) @@ -1111,49 +1112,35 @@ that are composite records, each containing two unsigned 8-bit integers accessed through the components `x` and `y`, and laid out in memory with the `x` component preceding the `y` component. +### Structures + +A _structure_ is a nominal [structure type](#structure-types) defined with the keyword `struct`. + +An example of a `struct` item and its use: + +~~~~ +struct Point {x: int, y: int} +let p = Point {x: 10, y: 11}; +let px: int = p.x; +~~~~ + ### Enumerations -An _enumeration item_ simultaneously declares a new nominal -[enumerated type](#enumerated-types) as well as a set of *constructors* that -can be used to create or pattern-match values of the corresponding enumerated -type. - -The constructors of an `enum` type may be recursive: that is, each constructor -may take an argument that refers, directly or indirectly, to the enumerated -type the constructor is a member of. Such recursion has restrictions: - -* Recursive types can be introduced only through `enum` constructors. -* A recursive `enum` item must have at least one non-recursive constructor (in - order to give the recursion a basis case). -* The recursive argument of recursive `enum` constructors must be [*box* - values](#box-types) (in order to bound the in-memory size of the - constructor). -* Recursive type definitions can cross module boundaries, but not module - *visibility* boundaries or crate boundaries (in order to simplify the - module system). +An _enumeration_ is a simulatneous definition of a nominal [enumerated type](#enumerated-types) as well as a set of *constructors*, +that can be used to create or pattern-match values of the corresponding enumerated type. +Enumerations are declared with the keyword `enum`. An example of an `enum` item and its use: ~~~~ -enum animal { - dog, - cat +enum Animal { + Dog, + Cat } -let mut a: animal = dog; -a = cat; -~~~~ - -An example of a *recursive* `enum` item and its use: - -~~~~ -enum list { - nil, - cons(T, @list) -} - -let a: list = cons(7, @cons(13, @nil)); +let mut a: Animal = Dog; +a = Cat; ~~~~ ### Constants @@ -2374,22 +2361,6 @@ A value of type `~str` is a Unicode string, represented as a vector of 8-bit unsigned bytes holding a sequence of UTF-8 codepoints. -### Record types - -The record type-constructor forms a new heterogeneous product of values.^[The -record type-constructor is analogous to the `struct` type-constructor in the -Algol/C family, the *record* types of the ML family, or the *structure* types -of the Lisp family.] Fields of a record type are accessed by name and are -arranged in memory in the order specified by the record type. - -An example of a record type and its use: - -~~~~ -type point = {x: int, y: int}; -let p: point = {x: 10, y: 11}; -let px: int = p.x; -~~~~ - ### Tuple types The tuple type-constructor forms a new heterogeneous product of values similar @@ -2414,6 +2385,7 @@ let (a, b) = p; assert b != ~"world"; ~~~~ + ### Vector types The vector type-constructor represents a homogeneous array of values of a @@ -2448,16 +2420,88 @@ All accessible elements of a vector are always initialized, and access to a vector is always bounds-checked. +### Structure types + +A `struct` *type* is a heterogeneous product of other types, called the *fields* of the type. +^[`struct` types are analogous `struct` types in C, +the *record* types of the ML family, +or the *structure* types of the Lisp family.] + +New instances of a `struct` can be constructed with a [struct expression](#struct-expressions). + +The memory order of fields in a `struct` is given by the item defining it. +Fields may be given in any order in a corresponding struct *expression*; +the resulting `struct` value will always be laid out in memory in the order specified by the corresponding *item*. + +The fields of a `struct` may be qualified by [visibility modifiers](#visibility-modifiers), +to restrict access to implementation-private data in a structure. + + ### Enumerated types -An *enumerated type* is a nominal, heterogeneous disjoint union type.^[The -`enum` type is analogous to a `data` constructor declaration in ML or a *pick -ADT* in Limbo.] An [`enum` *item*](#enumerations) consists of a number of -*constructors*, each of which is independently named and takes an optional -tuple of arguments. +An *enumerated type* is a nominal, heterogeneous disjoint union type, +denoted by the name of an [`enum` item](#enumerations). +^[The `enum` type is analogous to a `data` constructor declaration in ML, +or a *pick ADT* in Limbo.] + +An [`enum` item](#enumerations) declares both the type and a number of *variant constructors*, +each of which is independently named and takes an optional tuple of arguments. + +New instances of an `enum` can be constructed by calling one of the variant constructors, +in a [call expression](#call-expressions). + +Any `enum` value consumes as much memory as the largest variant constructor for its corresponding `enum` type. + +Enum types cannot be denoted *structurally* as types, +but must be denoted by named reference to an [`enum` item](#enumerations). + + +### Recursive types + +Nominal types -- [enumerations](#enumerated-types) and [structures](#structure-types) -- may be recursive. +That is, each `enum` 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), + or other structural types such as [vectors](#vector-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). +* The size of a recursive type must be finite; + in other words the recursive fields of the type must be [pointer types](#pointer-types). +* Recursive type definitions can cross module boundaries, but not module *visibility* boundaries, + or crate boundaries (in order to simplify the module system and type checker). + +An example of a *recursive* type and its use: + +~~~~ +enum List { + Nil, + Cons(T, @List) +} + +let a: List = Cons(7, @Cons(13, @Nil)); +~~~~ + + +### Record types + +> **Note:** Records are not nominal types, thus do not directly support recursion, visibility control, +> out-of-order field initialization, or coherent trait implementation. +> Records are therefore deprecared and will be removed in future versions of Rust. +> [Structure types](#structure-types) should be used instead. + +The record type-constructor forms a new heterogeneous product of values. +Fields of a record type are accessed by name and are arranged in memory in the order specified by the record type. + +An example of a record type and its use: + +~~~~ +type Point = {x: int, y: int}; +let p: Point = {x: 10, y: 11}; +let px: int = p.x; +~~~~ -Enumerated types cannot be denoted *structurally* as types, but must be -denoted by named reference to an [*enumeration* item](#enumerations). ### Pointer types @@ -2507,6 +2551,7 @@ Raw pointers (`*`) they exist to support interoperability with foreign code, and writing performance-critical or low-level functions. + ### Function types The function type-constructor `fn` forms new function types. A function type @@ -2553,10 +2598,6 @@ fn main() { In this example, the trait `printable` occurs as a type in both the type signature of `print`, and the cast expression in `main`. -### Struct types - -Every struct item defines a type. - ### Type parameters Within the body of an item that has type parameter declarations, the names of its type parameters are types: From d81196ce96b1d3da7bb718ed4c5e9d4810be896e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 11:47:46 -0700 Subject: [PATCH 089/292] manual: improve description of traits. --- doc/rust.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 5f5cde72cf97..dfec7a779acb 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1157,9 +1157,14 @@ The definition expression of a constant is limited to expression forms that can ### Traits -A _trait item_ describes a set of method types. [_implementation -items_](#implementations) can be used to provide implementations of -those methods for a specific type. +A _trait_ describes a set of method types. + +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 type](#trait-types). + +Traits are implemented for specific types through separate [implementations](#implementations). ~~~~ # type surface = int; @@ -1171,10 +1176,9 @@ trait shape { } ~~~~ -This defines a trait with two methods. All values that have -[implementations](#implementations) of this trait in scope can -have their `draw` and `bounding_box` methods called, using -`value.bounding_box()` [syntax](#field-expressions). +This defines a trait with two methods. +All values that have [implementations](#implementations) of this trait in scope can have their `draw` and `bounding_box` methods called, +using `value.bounding_box()` [syntax](#field-expressions). Type parameters can be specified for a trait to make it generic. These appear after the name, using the same syntax used in [generic From 06a17a7ce5c2e6ff71fd6d24706dce15f51b8580 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 11:57:12 -0700 Subject: [PATCH 090/292] manual: disambiguate field expressions from method-call expressions. --- doc/rust.md | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index dfec7a779acb..4e6e0a4184ee 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1178,7 +1178,7 @@ trait shape { This defines a trait with two methods. All values that have [implementations](#implementations) of this trait in scope can have their `draw` and `bounding_box` methods called, -using `value.bounding_box()` [syntax](#field-expressions). +using `value.bounding_box()` [syntax](#method-call-expressions). Type parameters can be specified for a trait to make it generic. These appear after the name, using the same syntax used in [generic @@ -1558,13 +1558,27 @@ let base = {x: 1, y: 2, z: 3}; {y: 0, z: 10, .. base}; ~~~~ +### Method-call expressions + +~~~~~~~~{.ebnf .gram} +method_call_expr : expr '.' ident paren_expr_list ; +~~~~~~~~ + +A _method call_ consists of an expression followed by a single dot, an identifier, and a parenthesized expression-list. +Method calls are resolved to methods on specific traits, +either statically dispatching to a method if the exact `self`-type of the left-hand-side is known, +or dynamically dispatching if the left-hand-side expression is an indirect [trait type](#trait-types). + + ### Field expressions ~~~~~~~~{.ebnf .gram} -field_expr : expr '.' expr +field_expr : expr '.' ident ~~~~~~~~ -A dot can be used to access a field in a record. +A _field expression_ consists of an expression followed by a single dot and an identifier, +when not immediately followed by a parenthesized expression-list (the latter is a [method call expression](#method-call-expressions)). +A field expression denotes a field of a [structure](#structure-types) or [record](#record-types). ~~~~~~~~ {.field} myrecord.myfield; @@ -1574,17 +1588,9 @@ myrecord.myfield; A field access on a record is an [lvalue](#lvalues-rvalues-and-temporaries) referring to the value of that field. When the field is mutable, it can be [assigned](#assignment-expressions) to. -When the type of the expression to the left of the dot is a boxed -record, it is automatically derferenced to make the field access -possible. +When the type of the expression to the left of the dot is a pointer to a record or structure, +it is automatically derferenced to make the field access possible. -Field access syntax is overloaded for [trait method](#traits) -access. When no matching field is found, or the expression to the left -of the dot is not a (boxed) record, an -[implementation](#implementations) that matches this type and the -given method name is looked up instead, and the result of the -expression is this method, with its _self_ argument bound to the -expression on the left of the dot. ### Vector expressions From c4237db60e35d00257f602a38530aadbc9143689 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 12:07:02 -0700 Subject: [PATCH 091/292] manual: capitalize examples, remove mention of named impls, change RC -> managed, clarify language. --- doc/rust.md | 111 +++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 57 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 4e6e0a4184ee..b2a1948ede47 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1167,12 +1167,12 @@ or constrained by some other [trait type](#trait-types). Traits are implemented for specific types through separate [implementations](#implementations). ~~~~ -# type surface = int; -# type bounding_box = int; +# type Surface = int; +# type BoundingBox = int; -trait shape { - fn draw(surface); - fn bounding_box() -> bounding_box; +trait Shape { + fn draw(Surface); + fn bounding_box() -> BoundingBox; } ~~~~ @@ -1181,70 +1181,69 @@ All values that have [implementations](#implementations) of this trait in scope using `value.bounding_box()` [syntax](#method-call-expressions). Type parameters can be specified for a trait to make it generic. -These appear after the name, using the same syntax used in [generic -functions](#generic-functions). +These appear after the trait name, using the same syntax used in [generic functions](#generic-functions). ~~~~ -trait seq { +trait Seq { fn len() -> uint; fn elt_at(n: uint) -> T; fn iter(fn(T)); } ~~~~ -Generic functions may use traits as bounds on their type -parameters. This will have two effects: only types that have the trait -may instantiate the parameter, and within the -generic function, the methods of the trait can be called on values -that have the parameter's type. For example: +Generic functions may use traits as _bounds_ on their type parameters. +This will have two effects: only types that have the trait may instantiate the parameter, +and within the generic function, +the methods of the trait can be called on values that have the parameter's type. +For example: ~~~~ -# type surface = int; -# trait shape { fn draw(surface); } +# type Surface = int; +# trait Shape { fn draw(Surface); } -fn draw_twice(surface: surface, sh: T) { +fn draw_twice(surface: Surface, sh: T) { sh.draw(surface); sh.draw(surface); } ~~~~ -Trait items also define a type with the same name as the -trait. Values of this type are created by -[casting](#type-cast-expressions) values (of a type for which an -implementation of the given trait is in scope) to the trait -type. +Traits also define a [type](#trait-types) 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. ~~~~ -# trait shape { } -# impl int: shape { } +# trait Shape { } +# impl int: Shape { } # let mycircle = 0; -let myshape: shape = mycircle as shape; +let myshape: Shape = @mycircle as @Shape; ~~~~ -The resulting value is a reference-counted box containing the value -that was cast along with information that identify the methods of the -implementation that was used. Values with a trait type can always -have methods from their trait called on them, and can be used to -instantiate type parameters that are bounded by their trait. +The resulting value is a managed box containing the value that was cast, +along with information that identify the methods of the implementation that was used. +Values with a trait type can have [methods called](#method-call-expressions) on them, +for any method in the trait, +and can be used to instantiate type parameters that are bounded by the trait. ### Implementations -An _implementation item_ provides an implementation of a -[trait](#traits) for a type. +An _implementation_ is an item that implements a [trait](#traits) for a specific type. + +Implementations are defined with the keyword `impl`. ~~~~ -# type point = {x: float, y: float}; -# type surface = int; -# type bounding_box = {x: float, y: float, width: float, height: float}; -# trait shape { fn draw(surface); fn bounding_box() -> bounding_box; } -# fn do_draw_circle(s: surface, c: circle) { } +# type Point = {x: float, y: float}; +# type Surface = int; +# type BoundingBox = {x: float, y: float, width: float, height: float}; +# trait Shape { fn draw(surface); fn bounding_box() -> BoundingBox; } +# fn do_draw_circle(s: Surface, c: Circle) { } -type circle = {radius: float, center: point}; +type Circle = {radius: float, center: point}; -impl circle: shape { - fn draw(s: surface) { do_draw_circle(s, self); } - fn bounding_box() -> bounding_box { +impl Circle: Shape { + fn draw(s: Surface) { do_draw_circle(s, self); } + fn bounding_box() -> BoundingBox { let r = self.radius; {x: self.center.x - r, y: self.center.y - r, width: 2.0 * r, height: 2.0 * r} @@ -1252,30 +1251,28 @@ impl circle: shape { } ~~~~ -It is possible to define an implementation without referring to a -trait. The methods in such an implementation can only be used -statically (as direct calls on the values of the type that the -implementation targets). In such an implementation, the type after the colon is omitted, -and the name is mandatory. Such implementations are -limited to nominal types (enums, structs) and the implementation must -appear in the same module or a sub-module as the receiver type. +It is possible to define an implementation without referring to a trait. +The methods in such an implementation can only be used statically +(as direct calls on the values of the type that the implementation targets). +In such an implementation, the type after the colon is omitted. +Such implementations are limited to nominal types (enums, structs), +and the implementation must appear in the same module or a sub-module as the `self` type. -_When_ a trait is specified, all methods declared as part of the -trait must be present, with matching types and type parameter -counts, in the implementation. +When a trait _is_ specified in an `impl`, +all methods declared as part of the trait must be implemented, +with matching types and type parameter counts. -An implementation can take type parameters, which can be different -from the type parameters taken by the trait it implements. They -are written after the name of the implementation, or if that is not -specified, after the `impl` keyword. +An implementation can take type parameters, +which can be different from the type parameters taken by the trait it implements. +Implementation parameters are written after after the `impl` keyword. ~~~~ -# trait seq { } +# trait Seq { } -impl ~[T]: seq { +impl ~[T]: Seq { ... } -impl u32: seq { +impl u32: Seq { /* Treat the integer as a sequence of bits */ } ~~~~ From a8e1d83103cdaa8391e99c8ecaff0f68b8c0ff9e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 12:10:01 -0700 Subject: [PATCH 092/292] manual: remove all mention of constraints. --- doc/rust.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index b2a1948ede47..f6c4e776973f 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -676,8 +676,8 @@ from outside the source file: either by an explicit `source_directive` in a referencing crate file, or by the filename of the source file itself. A source file that contains a `main` function can be compiled to an -executable. If a `main` function is present, it must have no [type parameters](#type-parameters) -and no [constraints](#constraints). Its return type must be [`nil`](#primitive-types) and it must take no arguments. +executable. If a `main` function is present, +its return type must be [`nil`](#primitive-types) and it must take no arguments. # Items and attributes @@ -2292,8 +2292,7 @@ execute after the `assert`. ## Types Every slot and value in a Rust program has a type. The _type_ of a *value* -defines the interpretation of the memory holding it. The type of a *slot* may -also include [constraints](#constraints). +defines the interpretation of the memory holding it. Built-in types and type-constructors are tightly integrated into the language, in nontrivial ways that are not possible to emulate in user-defined @@ -2562,8 +2561,8 @@ Raw pointers (`*`) ### Function types The function type-constructor `fn` forms new function types. A function type -consists of a sequence of input slots, an optional set of -[input constraints](#constraints) and an output slot. +consists of a set of function-type modifiers (`pure`, `unsafe`, `extern`, etc.), +a sequence of input slots and an output slot. An example of a `fn` type: From c2fd04f66a1bad48333f53bbced4bba65915d637 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 12:12:31 -0700 Subject: [PATCH 093/292] manual: s/Self type/Self types/. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index f6c4e776973f..9574fe3be438 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2620,7 +2620,7 @@ fn map(f: fn(A) -> B, xs: ~[A]) -> ~[B] { Here, `first` has type `B`, referring to `map`'s `B` type parameter; and `rest` has type `~[B]`, a vector type with element type `B`. -### Self type +### 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 From 78f29f2b1432aea73c33a48a0e6dc05777cc55e8 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 12:21:32 -0700 Subject: [PATCH 094/292] manual: remove vestigial mention of tasking from definition of statement (long story, been there since first public release). --- doc/rust.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 9574fe3be438..9843595ff581 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1412,10 +1412,7 @@ sequence expression evaluation. ## Statements A _statement_ is a component of a block, which is in turn a component of an -outer [expression](#expressions) or [function](#functions). When a function is -spawned into a [task](#tasks), the task *executes* statements in an order -determined by the body of the enclosing function. Each statement causes the -task to perform certain actions. +outer [expression](#expressions) or [function](#functions). Rust has two kinds of statement: [declaration statements](#declaration-statements) and From 25d8ca153e7a4b0787f3087df0e391f6a9300021 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 12:25:25 -0700 Subject: [PATCH 095/292] manual: pluralize; decls can introduce multiple names. --- doc/rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 9843595ff581..671bc7b1665d 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1420,8 +1420,8 @@ Rust has two kinds of statement: ### Declaration statements -A _declaration statement_ is one that introduces a *name* into the enclosing -statement block. The declared name may denote a new slot or a new item. +A _declaration statement_ is one that introduces one or more *names* into the enclosing statement block. +The declared names may denote new slots or new items. #### Item declarations From 43fd84a607561682b3288746b8ea84d897eec6aa Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 12:49:52 -0700 Subject: [PATCH 096/292] Fix doctest. --- doc/rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 671bc7b1665d..e1565aea3d75 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1236,10 +1236,10 @@ Implementations are defined with the keyword `impl`. # type Point = {x: float, y: float}; # type Surface = int; # type BoundingBox = {x: float, y: float, width: float, height: float}; -# trait Shape { fn draw(surface); fn bounding_box() -> BoundingBox; } +# trait Shape { fn draw(Surface); fn bounding_box() -> BoundingBox; } # fn do_draw_circle(s: Surface, c: Circle) { } -type Circle = {radius: float, center: point}; +type Circle = {radius: float, center: Point}; impl Circle: Shape { fn draw(s: Surface) { do_draw_circle(s, self); } From 009cf535a47a543801c35352ca17e092b63dd8c6 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 13:10:20 -0700 Subject: [PATCH 097/292] manual: add section for path expressions. --- doc/rust.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/rust.md b/doc/rust.md index e1565aea3d75..f7a70e9fd04b 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1503,6 +1503,11 @@ string, boolean value, or the nil value. 5; // integer type ~~~~~~~~ +### Path expressions + +A [path](#paths) used as an expression context denotes either a local variable or an item. +Path expressions are [lvalues](#lvalues-rvalues-and-temporaries). + ### Tuple expressions Tuples are written by enclosing two or more comma-separated From e257f390e12f3eb414152a474259ccd8641627aa Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 13:10:43 -0700 Subject: [PATCH 098/292] manual: add section for unary move expressions. --- doc/rust.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/rust.md b/doc/rust.md index f7a70e9fd04b..feed0a81778b 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1919,6 +1919,20 @@ mutate(copy v); // Pass a copy assert v[0] == 1; // Original was not modified ~~~~ +### Unary move expressions + +~~~~~~~~{.ebnf .gram} +move_expr : "move" expr ; +~~~~~~~~ + +A _unary move expression_ is similar to a [unary copy](#unary-copy-expressions) expression, +except that it can only be applied to an [lvalue](#lvalues-rvalues-and-temporaries), +and it performs a _move_ on its operand, rather than a copy. +That is, the memory location denoted by its operand is de-initialized after evaluation, +and the resulting value is a shallow copy of the operand, +even if the operand is an [owning type](#type-kinds). + + ### Call expressions ~~~~~~~~ {.abnf .gram} From c46706fffdfc54fcb19fee543e6ad8a4c4b79ca4 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 13:11:07 -0700 Subject: [PATCH 099/292] manual: add borrow operator to symbolic unary operator list; mention copy and move. --- doc/rust.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index feed0a81778b..a01a28f68a3c 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1636,8 +1636,9 @@ task in a _failing state_. ### Unary operator expressions -Rust defines five unary operators. They are all written as prefix -operators, before the expression they apply to. +Rust defines six symbolic unary operators, +in addition to the unary [copy](#unary-copy-expressions) and [move](#unary-move-expressions) operators. +They are all written as prefix operators, before the expression they apply to. `-` : Negation. May only be applied to numeric types. @@ -1652,9 +1653,12 @@ operators, before the expression they apply to. `false`. On integer types, this inverts the individual bits in the two's complement representation of the value. `@` and `~` - : [Boxing](#box-types) operators. Allocate a box to hold the value - they are applied to, and store the value in it. `@` creates a - shared, reference-counted box, whereas `~` creates a unique box. + : [Boxing](#pointer-types) operators. Allocate a box to hold the value they are applied to, + and store the value in it. `@` creates a managed box, whereas `~` creates an owned box. +`&` + : Borrow operator. Returns a borrowed pointer, pointing to its operand. + The operand of a borrowed pointer is statically proven to outlive the resulting pointer. + If the borrow-checker cannot prove this, it is a compilation error. ### Binary operator expressions From 2c34ffa26f4850c7bb648ebab0952b8a78874f12 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 13:11:21 -0700 Subject: [PATCH 100/292] manual: link to expressions in lval/rval section. --- doc/rust.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index a01a28f68a3c..4b3b9a4c1582 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1476,11 +1476,15 @@ Expressions are divided into two main categories: _lvalues_ and _rvalues_. Likewise within each expression, sub-expressions may occur in _lvalue context_ or _rvalue context_. The evaluation of an expression depends both on its own category and the context it occurs within. -Path, field and index expressions are lvalues. +[Path](#path-expressions), [field](#field-expressions) and [index](#index-expressions) expressions are lvalues. All other expressions are rvalues. -The left operand of an assignment, compound-assignment, or binary move expression is an lvalue context, -as is the single operand of a borrow, unary copy or move expression, and _both_ operands of a swap expression. +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), +or [move](#unary-move-expressions) expression, +and _both_ operands of a [swap](#swap-expressions) +or [binary move](#binary-move-expressions) expression. All other expression contexts are rvalue contexts. When an lvalue is evaluated in an _lvalue context_, it denotes a memory location; From 382e85c14f211e986b7e0efde6bc6f5edd6f249b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 13:12:29 -0700 Subject: [PATCH 101/292] manual: "with" -> ".." for FRU. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 4b3b9a4c1582..f0a469c02ccd 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1528,7 +1528,7 @@ values. ~~~~~~~~{.ebnf .gram} rec_expr : '{' ident ':' expr [ ',' ident ':' expr ] * - [ "with" expr ] '}' + [ ".." expr ] '}' ~~~~~~~~ A [_record_](#record-types) _expression_ is one or more comma-separated From c87ff5e29e3192db39a6c35662165e644cde7b9d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 13:13:58 -0700 Subject: [PATCH 102/292] manual: remove box-specific language. --- doc/rust.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index f0a469c02ccd..4fc403efd5e3 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1647,11 +1647,10 @@ They are all written as prefix operators, before the expression they apply to. `-` : Negation. May only be applied to numeric types. `*` - : Dereference. When applied to a [pointer](#pointer-types) it denotes the pointed-to location. For - mutable boxes, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to. For - [enums](#enumerated-types) that have only a single variant, - containing a single parameter, the dereference operator accesses - this parameter. + : Dereference. When applied to a [pointer](#pointer-types) it denotes the pointed-to location. + For pointers to mutable locations, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to. + For [enums](#enumerated-types) that have only a single variant, containing a single parameter, + the dereference operator accesses this parameter. `!` : Logical negation. On the boolean type, this flips between `true` and `false`. On integer types, this inverts the individual bits in the From 41bce91cb871ba90caf7d3e56243141dd3390bca Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 14:10:05 -0700 Subject: [PATCH 103/292] Fix tutorial link to tasks Closes #3715 --- doc/tutorial.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index ae88cda8d8e9..04fd2aae3f7d 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1630,7 +1630,9 @@ hold on to things that can safely be sent between processes. They copy the values they close over, much like managed closures, but they also own them: that is, no other code can access them. Owned closures are used in concurrent code, particularly -for spawning [tasks](#tasks). +for spawning [tasks][tasks]. + +[tasks]: tutorial-tasks.html ## Closure compatibility From 5a8ba073bcd6ee6fd34ff545845a746cddc4904f Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 14:12:50 -0700 Subject: [PATCH 104/292] Make to_str pure and fix const parameters for str-mutating functions Two separate changes that got intertwined (sorry): Make to_str pure. Closes #3691 In str, change functions like push_char to take an &mut str instead of an &str. Closes #3710 --- src/libcore/float.rs | 12 +++--- src/libcore/int-template.rs | 6 +-- src/libcore/path.rs | 4 +- src/libcore/str.rs | 22 +++++----- src/libcore/to_str.rs | 52 ++++++++++++------------ src/libcore/uint-template.rs | 2 +- src/libstd/json.rs | 29 ++++++------- src/libstd/map.rs | 3 +- src/libstd/net_url.rs | 20 +++++---- src/libsyntax/ext/pipes/proto.rs | 2 +- src/rustc/middle/liveness.rs | 4 +- src/test/auxiliary/cci_class_cast.rs | 2 +- src/test/run-pass/class-separate-impl.rs | 2 +- src/test/run-pass/issue-2904.rs | 2 +- 14 files changed, 87 insertions(+), 75 deletions(-) diff --git a/src/libcore/float.rs b/src/libcore/float.rs index 098e82f5fad7..dd46d30d6bad 100644 --- a/src/libcore/float.rs +++ b/src/libcore/float.rs @@ -91,7 +91,7 @@ pub mod consts { * * digits - The number of significant digits * * exact - Whether to enforce the exact number of significant digits */ -pub fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { +pub pure fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { if is_NaN(num) { return ~"NaN"; } if num == infinity { return ~"inf"; } if num == neg_infinity { return ~"-inf"; } @@ -125,7 +125,8 @@ pub fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { // store the next digit frac *= 10.0; let digit = frac as uint; - fractionalParts.push(digit); + // Bleh: not really unsafe. + unsafe { fractionalParts.push(digit); } // calculate the next frac frac -= digit as float; @@ -140,7 +141,8 @@ pub fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { // turn digits into string // using stack of digits while fractionalParts.is_not_empty() { - let mut adjusted_digit = carry + fractionalParts.pop(); + // Bleh; shouldn't need to be unsafe + let mut adjusted_digit = carry + unsafe { fractionalParts.pop() }; if adjusted_digit == 10 { carry = 1; @@ -196,7 +198,7 @@ pub fn test_to_str_exact_do_decimal() { * * num - The float value * * digits - The number of significant digits */ -pub fn to_str(num: float, digits: uint) -> ~str { +pub pure fn to_str(num: float, digits: uint) -> ~str { to_str_common(num, digits, false) } @@ -361,7 +363,7 @@ pub fn from_str(num: &str) -> Option { * * `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow` */ -pub fn pow_with_uint(base: uint, pow: uint) -> float { +pub pure fn pow_with_uint(base: uint, pow: uint) -> float { if base == 0u { if pow == 0u { return NaN as float; diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 8cb689fd286a..0ea7e1d29440 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -154,7 +154,7 @@ impl T : FromStr { } /// Convert to a string in a given base -pub fn to_str(n: T, radix: uint) -> ~str { +pub pure fn to_str(n: T, radix: uint) -> ~str { do to_str_bytes(n, radix) |slice| { do vec::as_imm_buf(slice) |p, len| { unsafe { str::raw::from_buf_len(p, len) } @@ -162,7 +162,7 @@ pub fn to_str(n: T, radix: uint) -> ~str { } } -pub fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { +pub pure fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { if n < 0 as T { uint::to_str_bytes(true, -n as uint, radix, f) } else { @@ -171,7 +171,7 @@ pub fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { } /// Convert to a string -pub fn str(i: T) -> ~str { return to_str(i, 10u); } +pub pure fn str(i: T) -> ~str { return to_str(i, 10u); } // FIXME: Has alignment issues on windows and 32-bit linux (#2609) #[test] diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 6d023ed1bfb7..e5d2397da0d7 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -61,7 +61,7 @@ pub pure fn Path(s: &str) -> Path { } impl PosixPath : ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { let mut s = ~""; if self.is_absolute { s += "/"; @@ -236,7 +236,7 @@ impl PosixPath : GenericPath { impl WindowsPath : ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { let mut s = ~""; match self.host { Some(ref h) => { s += "\\\\"; s += *h; } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 1256e5b5617c..aff4c50cfd2d 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -49,7 +49,7 @@ pub pure fn from_byte(b: u8) -> ~str { } /// Appends a character at the end of a string -pub fn push_char(s: &const ~str, ch: char) { +pub fn push_char(s: &mut ~str, ch: char) { unsafe { let code = ch as uint; let nb = if code < max_one_b { 1u } @@ -140,7 +140,7 @@ pub pure fn from_chars(chs: &[char]) -> ~str { /// Appends a string slice to the back of a string, without overallocating #[inline(always)] -pub fn push_str_no_overallocate(lhs: &const ~str, rhs: &str) { +pub fn push_str_no_overallocate(lhs: &mut ~str, rhs: &str) { unsafe { let llen = lhs.len(); let rlen = rhs.len(); @@ -157,7 +157,7 @@ pub fn push_str_no_overallocate(lhs: &const ~str, rhs: &str) { } /// Appends a string slice to the back of a string #[inline(always)] -pub fn push_str(lhs: &const ~str, rhs: &str) { +pub fn push_str(lhs: &mut ~str, rhs: &str) { unsafe { let llen = lhs.len(); let rlen = rhs.len(); @@ -214,7 +214,7 @@ Section: Adding to and removing from a string * * If the string does not contain any characters */ -pub fn pop_char(s: &const ~str) -> char { +pub fn pop_char(s: &mut ~str) -> char { let end = len(*s); assert end > 0u; let {ch, prev} = char_range_at_reverse(*s, end); @@ -1802,9 +1802,9 @@ pub pure fn as_buf(s: &str, f: fn(*u8, uint) -> T) -> T { * * s - A string * * n - The number of bytes to reserve space for */ -pub fn reserve(s: &const ~str, n: uint) { +pub fn reserve(s: &mut ~str, n: uint) { unsafe { - let v: *mut ~[u8] = cast::transmute(copy s); + let v: *mut ~[u8] = cast::transmute(s); vec::reserve(&mut *v, n + 1); } } @@ -1829,7 +1829,7 @@ pub fn reserve(s: &const ~str, n: uint) { * * s - A string * * n - The number of bytes to reserve space for */ -pub fn reserve_at_least(s: &const ~str, n: uint) { +pub fn reserve_at_least(s: &mut ~str, n: uint) { reserve(s, uint::next_power_of_two(n + 1u) - 1u) } @@ -1974,7 +1974,7 @@ pub mod raw { } /// Appends a byte to a string. (Not UTF-8 safe). - pub unsafe fn push_byte(s: &const ~str, b: u8) { + pub unsafe fn push_byte(s: &mut ~str, b: u8) { reserve_at_least(s, s.len() + 1); do as_buf(*s) |buf, len| { let buf: *mut u8 = ::cast::reinterpret_cast(&buf); @@ -1984,13 +1984,13 @@ pub mod raw { } /// Appends a vector of bytes to a string. (Not UTF-8 safe). - unsafe fn push_bytes(s: &const ~str, bytes: &[u8]) { + unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) { reserve_at_least(s, s.len() + bytes.len()); for vec::each(bytes) |byte| { push_byte(s, *byte); } } /// Removes the last byte from a string and returns it. (Not UTF-8 safe). - pub unsafe fn pop_byte(s: &const ~str) -> u8 { + pub unsafe fn pop_byte(s: &mut ~str) -> u8 { let len = len(*s); assert (len > 0u); let b = s[len - 1u]; @@ -2008,7 +2008,7 @@ pub mod raw { } /// Sets the length of the string and adds the null terminator - pub unsafe fn set_len(v: &const ~str, new_len: uint) { + pub unsafe fn set_len(v: &mut ~str, new_len: uint) { let v: **vec::raw::VecRepr = cast::transmute(copy v); let repr: *vec::raw::VecRepr = *v; (*repr).unboxed.fill = new_len + 1u; diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index a3659937ad45..fb0608906a11 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -8,80 +8,82 @@ The `ToStr` trait for converting to strings #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; -pub trait ToStr { fn to_str() -> ~str; } +pub trait ToStr { pure fn to_str() -> ~str; } impl int: ToStr { - fn to_str() -> ~str { int::str(self) } + pure fn to_str() -> ~str { int::str(self) } } impl i8: ToStr { - fn to_str() -> ~str { i8::str(self) } + pure fn to_str() -> ~str { i8::str(self) } } impl i16: ToStr { - fn to_str() -> ~str { i16::str(self) } + pure fn to_str() -> ~str { i16::str(self) } } impl i32: ToStr { - fn to_str() -> ~str { i32::str(self) } + pure fn to_str() -> ~str { i32::str(self) } } impl i64: ToStr { - fn to_str() -> ~str { i64::str(self) } + pure fn to_str() -> ~str { i64::str(self) } } impl uint: ToStr { - fn to_str() -> ~str { uint::str(self) } + pure fn to_str() -> ~str { uint::str(self) } } impl u8: ToStr { - fn to_str() -> ~str { u8::str(self) } + pure fn to_str() -> ~str { u8::str(self) } } impl u16: ToStr { - fn to_str() -> ~str { u16::str(self) } + pure fn to_str() -> ~str { u16::str(self) } } impl u32: ToStr { - fn to_str() -> ~str { u32::str(self) } + pure fn to_str() -> ~str { u32::str(self) } } impl u64: ToStr { - fn to_str() -> ~str { u64::str(self) } + pure fn to_str() -> ~str { u64::str(self) } } impl float: ToStr { - fn to_str() -> ~str { float::to_str(self, 4u) } + pure fn to_str() -> ~str { float::to_str(self, 4u) } } impl f32: ToStr { - fn to_str() -> ~str { float::to_str(self as float, 4u) } + pure fn to_str() -> ~str { float::to_str(self as float, 4u) } } impl f64: ToStr { - fn to_str() -> ~str { float::to_str(self as float, 4u) } + pure fn to_str() -> ~str { float::to_str(self as float, 4u) } } impl bool: ToStr { - fn to_str() -> ~str { bool::to_str(self) } + pure fn to_str() -> ~str { bool::to_str(self) } } impl (): ToStr { - fn to_str() -> ~str { ~"()" } + pure fn to_str() -> ~str { ~"()" } } impl ~str: ToStr { - fn to_str() -> ~str { copy self } + pure fn to_str() -> ~str { copy self } } impl &str: ToStr { - fn to_str() -> ~str { str::from_slice(self) } + pure fn to_str() -> ~str { str::from_slice(self) } } impl @str: ToStr { - fn to_str() -> ~str { str::from_slice(self) } + pure fn to_str() -> ~str { str::from_slice(self) } } impl (A, B): ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { let (a, b) = self; ~"(" + a.to_str() + ~", " + b.to_str() + ~")" } } impl (A, B, C): ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { let (a, b, c) = self; ~"(" + a.to_str() + ~", " + b.to_str() + ~", " + c.to_str() + ~")" } } impl ~[A]: ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str unsafe { + // Bleh -- not really unsafe + // push_str and push_char let mut acc = ~"[", first = true; - for vec::each(self) |elt| { + for vec::each(self) |elt| unsafe { if first { first = false; } else { str::push_str(&mut acc, ~", "); } str::push_str(&mut acc, elt.to_str()); @@ -92,10 +94,10 @@ impl ~[A]: ToStr { } impl @A: ToStr { - fn to_str() -> ~str { ~"@" + (*self).to_str() } + pure fn to_str() -> ~str { ~"@" + (*self).to_str() } } impl ~A: ToStr { - fn to_str() -> ~str { ~"~" + (*self).to_str() } + pure fn to_str() -> ~str { ~"~" + (*self).to_str() } } #[cfg(test)] diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index 7d0421c07301..00dd9be76db0 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -232,7 +232,7 @@ pub pure fn to_str_bytes(neg: bool, num: T, radix: uint, } /// Convert to a string -pub fn str(i: T) -> ~str { return to_str(i, 10u); } +pub pure fn str(i: T) -> ~str { return to_str(i, 10u); } #[test] pub fn test_to_str() { diff --git a/src/libstd/json.rs b/src/libstd/json.rs index fa7c0286dc1e..bb331240b765 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -51,7 +51,7 @@ fn escape_str(s: &str) -> ~str { fn spaces(n: uint) -> ~str { let mut ss = ~""; - for n.times { str::push_str(&ss, " "); } + for n.times { str::push_str(&mut ss, " "); } return ss; } @@ -302,7 +302,8 @@ pub fn to_writer(wr: io::Writer, json: &Json) { } /// Serializes a json value into a string -pub fn to_str(json: &Json) -> ~str { +pub pure fn to_str(json: &Json) -> ~str unsafe { + // ugh, should be safe io::with_str_writer(|wr| to_writer(wr, json)) } @@ -546,14 +547,14 @@ priv impl Parser { if (escape) { match self.ch { - '"' => str::push_char(&res, '"'), - '\\' => str::push_char(&res, '\\'), - '/' => str::push_char(&res, '/'), - 'b' => str::push_char(&res, '\x08'), - 'f' => str::push_char(&res, '\x0c'), - 'n' => str::push_char(&res, '\n'), - 'r' => str::push_char(&res, '\r'), - 't' => str::push_char(&res, '\t'), + '"' => str::push_char(&mut res, '"'), + '\\' => str::push_char(&mut res, '\\'), + '/' => str::push_char(&mut res, '/'), + 'b' => str::push_char(&mut res, '\x08'), + 'f' => str::push_char(&mut res, '\x0c'), + 'n' => str::push_char(&mut res, '\n'), + 'r' => str::push_char(&mut res, '\r'), + 't' => str::push_char(&mut res, '\t'), 'u' => { // Parse \u1234. let mut i = 0u; @@ -582,7 +583,7 @@ priv impl Parser { ~"invalid \\u escape (not four digits)"); } - str::push_char(&res, n as char); + str::push_char(&mut res, n as char); } _ => return self.error(~"invalid escape") } @@ -594,7 +595,7 @@ priv impl Parser { self.bump(); return Ok(res); } - str::push_char(&res, self.ch); + str::push_char(&mut res, self.ch); } } @@ -1166,11 +1167,11 @@ impl Option: ToJson { } impl Json: to_str::ToStr { - fn to_str() -> ~str { to_str(&self) } + pure fn to_str() -> ~str { to_str(&self) } } impl Error: to_str::ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { fmt!("%u:%u: %s", self.line, self.col, *self.msg) } } diff --git a/src/libstd/map.rs b/src/libstd/map.rs index 765d40339d3c..9f78f98fa316 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -341,7 +341,8 @@ pub mod chained { wr.write_str(~" }"); } - fn to_str() -> ~str { + pure fn to_str() -> ~str unsafe { + // Meh -- this should be safe do io::with_str_writer |wr| { self.to_writer(wr) } } } diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index 0ab4d89f3635..c3fd3383979b 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -94,7 +94,8 @@ pub fn encode(s: &str) -> ~str { * * This function is compliant with RFC 3986. */ -pub fn encode_component(s: &str) -> ~str { + +fn encode_component(s: &str) -> ~str { encode_inner(s, false) } @@ -297,7 +298,7 @@ fn userinfo_from_str(uinfo: &str) -> UserInfo { return UserInfo(user, pass); } -fn userinfo_to_str(userinfo: UserInfo) -> ~str { +pure fn userinfo_to_str(userinfo: UserInfo) -> ~str { if option::is_some(&userinfo.pass) { return str::concat(~[copy userinfo.user, ~":", option::unwrap(copy userinfo.pass), @@ -325,11 +326,15 @@ fn query_from_str(rawquery: &str) -> Query { return query; } -pub fn query_to_str(query: Query) -> ~str { +pub pure fn query_to_str(query: Query) -> ~str { let mut strvec = ~[]; for query.each |kv| { let (k, v) = copy *kv; - strvec += ~[#fmt("%s=%s", encode_component(k), encode_component(v))]; + // This is really safe... + unsafe { + strvec += ~[#fmt("%s=%s", + encode_component(k), encode_component(v))]; + } }; return str::connect(strvec, ~"&"); } @@ -672,7 +677,7 @@ impl Url : FromStr { * result in just "http://somehost.com". * */ -pub fn to_str(url: Url) -> ~str { +pub pure fn to_str(url: Url) -> ~str { let user = if url.user.is_some() { userinfo_to_str(option::unwrap(copy url.user)) } else { @@ -688,7 +693,8 @@ pub fn to_str(url: Url) -> ~str { } else { str::concat(~[~"?", query_to_str(url.query)]) }; - let fragment = if url.fragment.is_some() { + // ugh, this really is safe + let fragment = if url.fragment.is_some() unsafe { str::concat(~[~"#", encode_component( option::unwrap(copy url.fragment))]) } else { @@ -704,7 +710,7 @@ pub fn to_str(url: Url) -> ~str { } impl Url: to_str::ToStr { - pub fn to_str() -> ~str { + pub pure fn to_str() -> ~str { to_str(self) } } diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index 6d58d209fcfc..a501df4c32d2 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -18,7 +18,7 @@ impl direction : cmp::Eq { } impl direction: ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { match self { send => ~"Send", recv => ~"Recv" diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 12d63cdacbf6..3ae0727de60d 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -195,11 +195,11 @@ fn check_crate(tcx: ty::ctxt, } impl LiveNode: to_str::ToStr { - fn to_str() -> ~str { fmt!("ln(%u)", *self) } + pure fn to_str() -> ~str { fmt!("ln(%u)", *self) } } impl Variable: to_str::ToStr { - fn to_str() -> ~str { fmt!("v(%u)", *self) } + pure fn to_str() -> ~str { fmt!("v(%u)", *self) } } // ______________________________________________________________________ diff --git a/src/test/auxiliary/cci_class_cast.rs b/src/test/auxiliary/cci_class_cast.rs index 288fe66dd205..ca2af3875877 100644 --- a/src/test/auxiliary/cci_class_cast.rs +++ b/src/test/auxiliary/cci_class_cast.rs @@ -13,7 +13,7 @@ struct cat { } impl cat : ToStr { - fn to_str() -> ~str { self.name } + pure fn to_str() -> ~str { self.name } } priv impl cat { diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs index c7517ab1b3d2..8a51eb33857b 100644 --- a/src/test/run-pass/class-separate-impl.rs +++ b/src/test/run-pass/class-separate-impl.rs @@ -45,7 +45,7 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { } impl cat: ToStr { - fn to_str() -> ~str { self.name } + pure fn to_str() -> ~str { self.name } } fn print_out(thing: T, expected: ~str) { diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index 6d771dc7386e..4bb2c561422c 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -16,7 +16,7 @@ enum square { } impl square: to_str::ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { match self { bot => { ~"R" } wall => { ~"#" } From 1ab914df1d24f6c198bb7b1e01a4cf0050d179c8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 14:14:46 -0700 Subject: [PATCH 105/292] Write option::chain and result::chain with `match move` Closes #3590 --- src/libcore/option.rs | 8 +++----- src/libcore/result.rs | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index c60b7b401cc8..e970f00c5fbb 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -119,11 +119,9 @@ pub pure fn chain(opt: Option, * function that returns an option. */ - // XXX write with move match - if opt.is_some() { - f(unwrap(opt)) - } else { - None + match move opt { + Some(move t) => f(t), + None => None } } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 39fae8905f92..611d62394357 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -105,11 +105,9 @@ pub pure fn to_either(res: &Result) */ pub fn chain(res: Result, op: fn(t: T) -> Result) -> Result { - // XXX: Should be writable with move + match - if res.is_ok() { - op(unwrap(res)) - } else { - Err(unwrap_err(res)) + match move res { + Ok(move t) => op(t), + Err(move e) => Err(e) } } From d8822742845fbb70de4d9cf07732058a1e7eeacb Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 14:17:24 -0700 Subject: [PATCH 106/292] Remove Copy bound from std::timer::delayed_send Closes #3717 --- src/libstd/timer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index c9c28c4e1f08..cc62e32608bc 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -23,7 +23,7 @@ use comm = core::comm; * * ch - a channel of type T to send a `val` on * * val - a value of type T to send over the provided `ch` */ -pub fn delayed_send(iotask: IoTask, +pub fn delayed_send(iotask: IoTask, msecs: uint, ch: comm::Chan, val: T) { unsafe { let timer_done_po = core::comm::Port::<()>(); From 3a2e9e404a3042d8642084cfe391804bd924b48c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 13:29:00 -0700 Subject: [PATCH 107/292] manual: s/unique/owned/, s/shared/managed/, fix rval/lval more. --- doc/rust.md | 80 ++++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 4fc403efd5e3..e6671766e794 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1479,12 +1479,12 @@ The evaluation of an expression depends both on its own category and the context [Path](#path-expressions), [field](#field-expressions) and [index](#index-expressions) expressions are lvalues. All other expressions are rvalues. -The left operand of an [assignment](#assignment-expressions) or +The left operand of an [assignment](#assignment-expressions), +[binary move](#binary-move-expressions) or [compound-assignment](#compound-assignment-expressions) expression is an lvalue context, as is the single operand of a unary [borrow](#unary-operator-expressions), or [move](#unary-move-expressions) expression, -and _both_ operands of a [swap](#swap-expressions) -or [binary move](#binary-move-expressions) expression. +and _both_ operands of a [swap](#swap-expressions) expression. All other expression contexts are rvalue contexts. When an lvalue is evaluated in an _lvalue context_, it denotes a memory location; @@ -1737,8 +1737,6 @@ and `&&` only when it evaluates to `true`. The binary comparison operators can be applied to any two operands of the same type, and produce a boolean value. -*TODO* details on how types are descended during comparison. - #### Type cast expressions A type cast expression is denoted with the binary operator `as`. @@ -1774,15 +1772,16 @@ types. A _binary move expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) followed by a left-pointing arrow (`<-`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression. -Evaluating a move expression causes, as a side effect, the rvalue to be -*moved* into the lvalue. If the rvalue was itself an lvalue, it must be a -local variable, as it will be de-initialized in the process. +Evaluating a move expression causes, as a side effect, +the rvalue to be *moved* into the lvalue. +If the rvalue was itself an lvalue, it must be a local variable, +as it will be de-initialized in the process. -Evaluating a move expression does not change reference counts, nor does it -cause a deep copy of any unique structure pointed to by the moved -*rval*. Instead, the move expression represents an indivisible *transfer of -ownership* from the right-hand-side to the left-hand-side of the -expression. No allocation or destruction is entailed. +Evaluating a move expression does not change reference counts, +nor does it cause a deep copy of any owned structure pointed to by the moved rvalue. +Instead, the move expression represents an indivisible *transfer of ownership* +from the right-hand-side to the left-hand-side of the expression. +No allocation or destruction is entailed. An example of three different move expressions: @@ -1805,8 +1804,10 @@ A _swap expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) fo Evaluating a swap expression causes, as a side effect, the values held in the left-hand-side and right-hand-side [lvalues](#lvalues-rvalues-and-temporaries) to be exchanged indivisibly. -Evaluating a swap expression neither changes reference counts nor deeply copies any unique structure pointed to by the moved [rvalue](#lvalues-rvalues-and-temporaries). -Instead, the swap expression represents an indivisible *exchange of ownership* between the right-hand-side and the left-hand-side of the expression. +Evaluating a swap expression neither changes reference counts, +nor deeply copies any owned structure pointed to by the moved [rvalue](#lvalues-rvalues-and-temporaries). +Instead, the swap expression represents an indivisible *exchange of ownership*, +between the right-hand-side and the left-hand-side of the expression. No allocation or destruction is entailed. An example of three different swap expressions: @@ -1904,13 +1905,12 @@ Evaluating a copy expression first evaluates the argument expression, then copies the resulting value, allocating any memory necessary to hold the new copy. -[Shared boxes](#box-types) (type `@`) are, as usual, shallow-copied, as they -may be cyclic. [Unique boxes](#box-types), [vectors](#vector-types) and -similar unique types are deep-copied. +[Managed boxes](#pointer-types) (type `@`) are, as usual, shallow-copied, +as are raw and borrowed pointers. +[Owned boxes](#pointer-types), [owned vectors](#vector-types) and similar owned types are deep-copied. -Since the binary [assignment operator](#assignment-expressions) `=` performs a -copy implicitly, the unary copy operator is typically only used to cause an -argument to a function to be copied and passed by value. +Since the binary [assignment operator](#assignment-expressions) `=` performs a copy implicitly, +the unary copy operator is typically only used to cause an argument to a function to be copied and passed by value. An example of a copy expression: @@ -2670,15 +2670,15 @@ kinds are: Sendable : Values with a sendable type can be safely sent to another task. - This kind includes scalars, unique pointers, unique closures, and + This kind includes scalars, owning pointers, owned closures, and structural types containing only other sendable types. Copyable : This kind includes all types that can be copied. All types with - sendable kind are copyable, as are shared boxes, shared closures, + sendable kind are copyable, as are managed boxes, managed closures, trait types, and structural types built out of these. Noncopyable : [Resource](#resources) types, and every type that includes a - resource without storing it in a shared box, may not be copied. + resource without storing it in a managed box, may not be copied. Types of sendable or copyable type can always be used in places where a noncopyable type is expected, so in effect this kind includes all types. @@ -2696,7 +2696,7 @@ declared for it. For example, this is not a valid program: fn box(x: T) -> @T { @x } ~~~~ -Putting `x` into a shared box involves copying, and the `T` parameter +Putting `x` into a managed box involves copying, and the `T` parameter is assumed to be noncopyable. To change that, a bound is declared: ~~~~ @@ -2746,7 +2746,7 @@ entry to each function as the task executes. A stack allocation is reclaimed when control leaves the frame containing it. The _heap_ is a general term that describes two separate sets of boxes: -shared boxes -- which may be subject to garbage collection -- and unique +managed boxes -- which may be subject to garbage collection -- and owned boxes. The lifetime of an allocation in the heap depends on the lifetime of the box values pointing to it. Since box values may themselves be passed in and out of frames, or stored in the heap, heap allocations may outlive the @@ -2765,13 +2765,13 @@ it is only instantiated for (transitively) sendable kinds of data constructor an never including managed or borrowed pointers. When a stack frame is exited, its local allocations are all released, and its -references to boxes (both shared and owned) are dropped. +references to boxes (both managed and owned) are dropped. -A shared box may (in the case of a recursive, mutable shared type) be cyclic; -in this case the release of memory inside the shared structure may be deferred +A managed box may (in the case of a recursive, mutable managed type) be cyclic; +in this case the release of memory inside the managed structure may be deferred until task-local garbage collection can reclaim it. Code can ensure no such -delayed deallocation occurs by restricting itself to unique boxes and similar -unshared kinds of data. +delayed deallocation occurs by restricting itself to owned boxes and similar +unmanaged kinds of data. When a task finishes, its stack is necessarily empty and it therefore has no references to any boxes; the remainder of its heap is immediately freed. @@ -2820,22 +2820,22 @@ fn incr(i: &mut int) { ### Memory boxes A _box_ is a reference to a heap allocation holding another value. There -are two kinds of boxes: *shared boxes* and *unique boxes*. +are two kinds of boxes: *managed boxes* and *owned boxes*. -A _shared box_ type or value is constructed by the prefix *at* sigil `@`. +A _managed box_ type or value is constructed by the prefix *at* sigil `@`. -A _unique box_ type or value is constructed by the prefix *tilde* sigil `~`. +An _owned box_ type or value is constructed by the prefix *tilde* sigil `~`. -Multiple shared box values can point to the same heap allocation; copying a -shared box value makes a shallow copy of the pointer (optionally incrementing -a reference count, if the shared box is implemented through +Multiple managed box values can point to the same heap allocation; copying a +managed box value makes a shallow copy of the pointer (optionally incrementing +a reference count, if the managed box is implemented through reference-counting). -Unique box values exist in 1:1 correspondence with their heap allocation; -copying a unique box value makes a deep copy of the heap allocation and +Owned box values exist in 1:1 correspondence with their heap allocation; +copying an owned box value makes a deep copy of the heap allocation and produces a pointer to the new allocation. -An example of constructing one shared box type and value, and one unique box +An example of constructing one managed box type and value, and one owned box type and value: ~~~~~~~~ From edf493f07b5316363a3ced23572c7ed79310b048 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 13:58:55 -0700 Subject: [PATCH 108/292] manual: fix exponents on number types. --- doc/rust.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index e6671766e794..66e143734b56 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2342,12 +2342,12 @@ The machine types are the following: * The unsigned word types `u8`, `u16`, `u32` and `u64`, with values drawn from - the integer intervals $[0, 2^8 - 1]$, $[0, 2^16 - 1]$, $[0, 2^32 - 1]$ and - $[0, 2^64 - 1]$ respectively. + the integer intervals $[0, 2^8 - 1]$, $[0, 2^{16} - 1]$, $[0, 2^{32} - 1]$ and + $[0, 2^{64} - 1]$ respectively. * The signed two's complement word types `i8`, `i16`, `i32` and `i64`, with values drawn from the integer intervals $[-(2^7), 2^7 - 1]$, - $[-(2^15), 2^15 - 1]$, $[-(2^31), 2^31 - 1]$, $[-(2^63), 2^63 - 1]$ + $[-(2^{15}), 2^{15} - 1]$, $[-(2^{31}), 2^{31} - 1]$, $[-(2^{63}), 2^{63} - 1]$ respectively. * The IEEE 754-2008 `binary32` and `binary64` floating-point types: `f32` and From eff4a36b3e5cfbd2b08bb5a3e8d07396dc532033 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 14:09:44 -0700 Subject: [PATCH 109/292] manual: mention overloading, traits on the arithmetic and bitwise operators. --- doc/rust.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 66e143734b56..fb5337baf2ed 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1674,40 +1674,49 @@ Binary operators expressions are given in terms of #### Arithmetic operators -Binary arithmetic expressions require both their operands to be of the -same type, and can be applied only to numeric types, with the -exception of `+`, which acts both as addition operator on numbers and -as concatenate operator on vectors and strings. +Binary arithmetic expressions are syntactic sugar for calls to built-in traits, +defined in the `core::ops` module of the `core` library. +This means that arithmetic operators can be overridden for user-defined types. +The default meaning of the operators on standard types is given here. `+` : Addition and vector/string concatenation. + Calls the `add` method on the `core::ops::Add` trait. `-` : Subtraction. + Calls the `sub` method on the `core::ops::Sub` trait. `*` : Multiplication. + Calls the `mul` method on the `core::ops::Mul` trait. `/` : Division. + Calls the `div` method on the `core::ops::Div` trait. `%` - : Remainder. + : Modulo (a.k.a. "remainder"). + Calls the `modulo` method on the `core::ops::Modulo` trait. #### Bitwise operators -Bitwise operators apply only to integer types, and perform their -operation on the bits of the two's complement representation of the -values. +Bitwise operators apply are, like the [arithmetic operators](#arithmetic-operators), +syntactic sugar for calls to built-in traits. +This means that bitwise operators can be overridden for user-defined types. +The default meaning of the operators on standard types is given here. `&` : And. + Calls the `bitand` method on the `core::ops::BitAnd` trait. `|` : Inclusive or. + Calls the `bitor` method on the `core::ops::BitOr` trait. `^` : Exclusive or. + Calls the `bitxor` method on the `core::ops::BitXor` trait. `<<` : Logical left shift. + Calls the `shl` method on the `core::ops::Shl` trait. `>>` : Logical right shift. -`>>>` - : Arithmetic right shift. + Calls the `shr` method on the `core::ops::Shr` trait. #### Lazy boolean operators From 1d47c0a830ac6d735128d3c6cd7ff3b41b874f94 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 14:17:54 -0700 Subject: [PATCH 110/292] manual: note overloading and traits for comparison ops. --- doc/rust.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index fb5337baf2ed..32830978de00 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1697,7 +1697,7 @@ The default meaning of the operators on standard types is given here. #### Bitwise operators -Bitwise operators apply are, like the [arithmetic operators](#arithmetic-operators), +Bitwise operators are, like the [arithmetic operators](#arithmetic-operators), syntactic sugar for calls to built-in traits. This means that bitwise operators can be overridden for user-defined types. The default meaning of the operators on standard types is given here. @@ -1730,21 +1730,31 @@ and `&&` only when it evaluates to `true`. #### Comparison operators +Comparison operators are, like the [arithmetic operators](#arithmetic-operators), +and [bitwise operators](#bitwise-operators), +syntactic sugar for calls to built-in traits. +This means that comparison operators can be overridden for user-defined types. +The default meaning of the operators on standard types is given here. + `==` : Equal to. + Calls the `eq` method on the `core::cmp::Eq` trait. `!=` : Unequal to. + Calls the `ne` method on the `core::cmp::Eq` trait. `<` : Less than. + Calls the `lt` method on the `core::cmp::Ord` trait. `>` : Greater than. + Calls the `gt` method on the `core::cmp::Ord` trait. `<=` : Less than or equal. + Calls the `le` method on the `core::cmp::Ord` trait. `>=` : Greater than or equal. + Calls the `ge` method on the `core::cmp::Ord` trait. -The binary comparison operators can be applied to any two operands of -the same type, and produce a boolean value. #### Type cast expressions From 44f8a8ec5ac85eb396ba2069752cb4d031d9e867 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 14:18:25 -0700 Subject: [PATCH 111/292] manual: remove 'trivial cast', it's an unused definition. --- doc/rust.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 32830978de00..245eaf46ad80 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1780,11 +1780,6 @@ fn avg(v: ~[float]) -> float { } ~~~~ -A cast is a *trivial cast* iff the type of the casted expression and the -target type are identical after replacing all occurrences of `int`, `uint`, -`float` with their machine type equivalents of the target architecture in both -types. - #### Binary move expressions From 04e6b09c580ea014e9d51f11f12e760c49a4df8e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 14:19:48 -0700 Subject: [PATCH 112/292] manual: remove mention of >>>. --- doc/rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 245eaf46ad80..db2cc800556c 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1861,7 +1861,7 @@ The former is just more terse and familiar. #### Compound assignment expressions -The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, `>>`, and `>>>` +The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be composed with the `=` operator. The expression `lval OP= val` is equivalent to `lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`. @@ -1877,7 +1877,7 @@ from strong to weak: * / % as + - -<< >> >>> +<< >> & ^ | From 2bb141c1f9c486442e57d255b4a7afafc9e89667 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 14:20:40 -0700 Subject: [PATCH 113/292] manual: remove mention of do-while loops. --- doc/rust.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index db2cc800556c..8db0d9ffdbf7 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1986,8 +1986,7 @@ let x: int = add(1, 2); ### While loops ~~~~~~~~{.ebnf .gram} -while_expr : "while" expr '{' block '}' - | "do" '{' block '}' "while" expr ; +while_expr : "while" expr '{' block '}' ; ~~~~~~~~ A `while` loop begins by evaluating the boolean loop conditional expression. From 1a885f6be13e5ad241e4597a13e919803942e65b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 14:42:11 -0700 Subject: [PATCH 114/292] manual: add section on lambda expressions. --- doc/rust.md | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 8db0d9ffdbf7..628cb1370613 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1975,13 +1975,47 @@ An example of a call expression: let x: int = add(1, 2); ~~~~ -### Shared function expressions +### Lambda expressions -*TODO*. +~~~~~~~~ {.abnf .gram} +ident_list : [ ident [ ',' ident ]* ] ? ; +lambda_expr : '|' ident_list '| expr ; +~~~~~~~~ -### Unique function expressions +A _lambda expression_ (a.k.a. "anonymous function expression") defines a function and denotes it as a value, +in a single expression. +Lambda expressions are written by prepending a list of identifiers, surrounded by pipe symbols (`|`), +to an expression. -*TODO*. +A lambda expression denotes a function mapping parameters to the expression to the right of the `ident_list`. +The identifiers in the `ident_list` are the parameters to the function, with types inferred from context. + +Lambda expressions are most useful when passing functions as arguments to other functions, +as an abbreviation for defining and capturing a separate fucntion. + +Significantly, lambda expressions _capture their environment_, +which regular [function definitions](#functions) do not. + +The exact type of capture depends on the [function type](#function-types) inferred for the lambda expression; +in the simplest and least-expensive form, the environment is captured by reference, +effectively borrowing pointers to all outer variables referenced inside the function. +Other forms of capture include making copies of captured variables, +and moving values from the environment into the lambda expression's captured environment. + +An example of a lambda expression: + +~~~~ +fn ten_times(f: fn(int)) { + let mut i = 0; + while i < 10 { + f(i); + i += 1; + } +} + +ten_times(|j| io::println(fmt!("hello, %d", j))); + +~~~~ ### While loops From f6606aff6e7024d40da74bdffc82983e678186a4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 14:40:50 -0700 Subject: [PATCH 115/292] Remove invalid FIXME --- src/libcore/int-template.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 0ea7e1d29440..5a2b054dd3e8 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -50,7 +50,6 @@ pub pure fn compl(i: T) -> T { } /// Computes the absolute value -// FIXME: abs should return an unsigned int (#2353) pub pure fn abs(i: T) -> T { if is_negative(i) { -i } else { i } } From 71813b3793651523fec39b1af1627881c64761f4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 14:41:47 -0700 Subject: [PATCH 116/292] Exports are fixed, hooray --- src/libcore/libc.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 3665128bf3ca..dd8f76c89d5f 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -42,8 +42,6 @@ // Initial glob-exports mean that all the contents of all the modules // wind up exported, if you're interested in writing platform-specific code. -// FIXME (#2006): change these to glob-exports when sufficiently supported. - pub use types::common::c95::*; pub use types::common::c99::*; pub use types::common::posix88::*; From fc4da29b4f5e5b5eb4a5c47c724edde399d28145 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 14:52:41 -0700 Subject: [PATCH 117/292] Update FIXME number --- src/libcore/private.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/private.rs b/src/libcore/private.rs index c4ef136a592e..b7be29d8fbdc 100644 --- a/src/libcore/private.rs +++ b/src/libcore/private.rs @@ -544,7 +544,7 @@ impl Exclusive { } } -// FIXME(#2585) make this a by-move method on the exclusive +// FIXME(#3724) make this a by-move method on the exclusive pub fn unwrap_exclusive(arc: Exclusive) -> T { let Exclusive { x: x } <- arc; let inner = unsafe { unwrap_shared_mutable_state(move x) }; From 27490769cee7d06e5514786a4728260ab4dcc36b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 14:57:13 -0700 Subject: [PATCH 118/292] Update FIXME number --- src/libcore/task.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/task.rs b/src/libcore/task.rs index 8d7791d18d90..1bb232030075 100644 --- a/src/libcore/task.rs +++ b/src/libcore/task.rs @@ -217,7 +217,7 @@ pub type TaskOpts = { // sidestep that whole issue by making builders uncopyable and making // the run function move them in. -// FIXME (#2585): Replace the 'consumed' bit with move mode on self +// FIXME (#3724): Replace the 'consumed' bit with move mode on self pub enum TaskBuilder = { opts: TaskOpts, gen_body: fn@(v: fn~()) -> fn~(), @@ -349,7 +349,7 @@ impl TaskBuilder { * Fails if a future_result was already set for this task. */ fn future_result(blk: fn(v: future::Future)) -> TaskBuilder { - // FIXME (#1087, #1857): Once linked failure and notification are + // FIXME (#3725): Once linked failure and notification are // handled in the library, I can imagine implementing this by just // registering an arbitrary number of task::on_exit handlers and // sending out messages. @@ -758,8 +758,8 @@ pub unsafe fn atomically(f: fn() -> U) -> U { fn test_cant_dup_task_builder() { let b = task().unlinked(); do b.spawn { } - // FIXME(#2585): For now, this is a -runtime- failure, because we haven't - // got modes on self. When 2585 is fixed, this test should fail to compile + // FIXME(#3724): For now, this is a -runtime- failure, because we haven't + // got move mode on self. When 3724 is fixed, this test should fail to compile // instead, and should go in tests/compile-fail. do b.spawn { } // b should have been consumed by the previous call } From d2efd7edf70be1a97b7de8709231963bb45ae33f Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 15:32:09 -0700 Subject: [PATCH 119/292] Update FIXME number --- src/libstd/sync.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index 908f3936f4e1..dd1dab835876 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -146,7 +146,7 @@ impl &Sem<~[mut Waitqueue]> { } } -// FIXME(#3136) should go inside of access() +// FIXME(#3588) should go inside of access() #[doc(hidden)] struct SemRelease { sem: &Sem<()>, @@ -577,7 +577,7 @@ impl &RWlock { } } -// FIXME(#3136) should go inside of read() +// FIXME(#3588) should go inside of read() #[doc(hidden)] struct RWlockReleaseRead { lock: &RWlock, @@ -606,7 +606,7 @@ fn RWlockReleaseRead(lock: &r/RWlock) -> RWlockReleaseRead/&r { } } -// FIXME(#3136) should go inside of downgrade() +// FIXME(#3588) should go inside of downgrade() #[doc(hidden)] struct RWlockReleaseDowngrade { lock: &RWlock, From bfbb7197d71a6ba48904e06e694bb53810825cf4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 15:35:31 -0700 Subject: [PATCH 120/292] Update FIXME numbers --- src/libsyntax/ast.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a27336097d0c..435f52b4bf82 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -437,7 +437,7 @@ impl proto : cmp::Eq { #[auto_serialize] #[auto_deserialize] enum vstore { - // FIXME (#2112): Change uint to @expr (actually only constant exprs) + // FIXME (#3469): Change uint to @expr (actually only constant exprs) vstore_fixed(Option), // [1,2,3,4]/_ or 4 vstore_uniq, // ~[1,2,3,4] vstore_box, // @[1,2,3,4] @@ -447,7 +447,7 @@ enum vstore { #[auto_serialize] #[auto_deserialize] enum expr_vstore { - // FIXME (#2112): Change uint to @expr (actually only constant exprs) + // FIXME (#3469): Change uint to @expr (actually only constant exprs) expr_vstore_fixed(Option), // [1,2,3,4]/_ or 4 expr_vstore_uniq, // ~[1,2,3,4] expr_vstore_box, // @[1,2,3,4] From 6854265161fa2ee23fca58cc1bcfad183c4b3730 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 15:37:37 -0700 Subject: [PATCH 121/292] Remove comment that is now false --- src/libcore/flate.rs | 4 ++-- src/libcore/task.rs | 4 ++-- src/libcore/vec.rs | 50 +++++++++++++++++++++++++-------------- src/libstd/arc.rs | 4 ++-- src/libstd/net_tcp.rs | 6 ++--- src/libsyntax/ast_util.rs | 1 - 6 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/libcore/flate.rs b/src/libcore/flate.rs index 7c5176494a22..b2dd468236a6 100644 --- a/src/libcore/flate.rs +++ b/src/libcore/flate.rs @@ -37,7 +37,7 @@ pub fn deflate_bytes(bytes: &[const u8]) -> ~[u8] { ptr::addr_of(&outsz), lz_norm); assert res as int != 0; - let out = vec::raw::from_buf(res as *u8, + let out = vec::raw::from_buf_raw(res as *u8, outsz as uint); libc::free(res); move out @@ -55,7 +55,7 @@ pub fn inflate_bytes(bytes: &[const u8]) -> ~[u8] { ptr::addr_of(&outsz), 0); assert res as int != 0; - let out = vec::raw::from_buf(res as *u8, + let out = vec::raw::from_buf_raw(res as *u8, outsz as uint); libc::free(res); move out diff --git a/src/libcore/task.rs b/src/libcore/task.rs index 1bb232030075..afc4a821bb6d 100644 --- a/src/libcore/task.rs +++ b/src/libcore/task.rs @@ -759,8 +759,8 @@ fn test_cant_dup_task_builder() { let b = task().unlinked(); do b.spawn { } // FIXME(#3724): For now, this is a -runtime- failure, because we haven't - // got move mode on self. When 3724 is fixed, this test should fail to compile - // instead, and should go in tests/compile-fail. + // got move mode on self. When 3724 is fixed, this test should fail to + // compile instead, and should go in tests/compile-fail. do b.spawn { } // b should have been consumed by the previous call } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 3a2b73f5b5b4..5d6e8584664a 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1657,9 +1657,22 @@ impl ~[T]: MutableEqVector { } } + +/** +* Constructs a vector from an unsafe pointer to a buffer +* +* # Arguments +* +* * ptr - An unsafe pointer to a buffer of `T` +* * elts - The number of elements in the buffer +*/ +// Wrapper for fn in raw: needs to be called by net_tcp::on_tcp_read_cb +pub unsafe fn from_buf(ptr: *T, elts: uint) -> ~[T] { + raw::from_buf_raw(ptr, elts) +} + /// Unsafe operations -pub mod raw { - // FIXME: This should have crate visibility (#1893 blocks that) +mod raw { /// The internal representation of a (boxed) vector pub struct VecRepr { @@ -1679,22 +1692,6 @@ pub mod raw { mut len: uint }; - /** - * Constructs a vector from an unsafe pointer to a buffer - * - * # Arguments - * - * * ptr - An unsafe pointer to a buffer of `T` - * * elts - The number of elements in the buffer - */ - #[inline(always)] - pub unsafe fn from_buf(ptr: *T, elts: uint) -> ~[T] { - let mut dst = with_capacity(elts); - set_len(&mut dst, elts); - as_mut_buf(dst, |p_dst, _len_dst| ptr::memcpy(p_dst, ptr, elts)); - move dst - } - /** * Sets the length of a vector * @@ -1775,6 +1772,23 @@ pub mod raw { } } + /** + * Constructs a vector from an unsafe pointer to a buffer + * + * # Arguments + * + * * ptr - An unsafe pointer to a buffer of `T` + * * elts - The number of elements in the buffer + */ + // Was in raw, but needs to be called by net_tcp::on_tcp_read_cb + #[inline(always)] + pub unsafe fn from_buf_raw(ptr: *T, elts: uint) -> ~[T] { + let mut dst = with_capacity(elts); + set_len(&mut dst, elts); + as_mut_buf(dst, |p_dst, _len_dst| ptr::memcpy(p_dst, ptr, elts)); + move dst + } + /** * Copies data from one vector to another. * diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index addabb2ddb9b..6178e64ff18c 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -190,7 +190,7 @@ impl &MutexARC { * * Will additionally fail if another task has failed while accessing the arc. */ -// FIXME(#2585) make this a by-move method on the arc +// FIXME(#3724) make this a by-move method on the arc pub fn unwrap_mutex_arc(arc: MutexARC) -> T { let MutexARC { x: x } <- arc; let inner = unsafe { unwrap_shared_mutable_state(move x) }; @@ -368,7 +368,7 @@ impl &RWARC { * Will additionally fail if another task has failed while accessing the arc * in write mode. */ -// FIXME(#2585) make this a by-move method on the arc +// FIXME(#3724) make this a by-move method on the arc pub fn unwrap_rw_arc(arc: RWARC) -> T { let RWARC { x: x, _ } <- arc; let inner = unsafe { unwrap_shared_mutable_state(move x) }; diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 249551fbb7df..87dea021f5b7 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -6,9 +6,7 @@ use ip = net_ip; use uv::iotask; use uv::iotask::IoTask; use future_spawn = future::spawn; -// FIXME #1935 -// should be able to, but can't atm, replace w/ result::{result, extensions}; -use result::*; +use result::{Result}; use libc::size_t; use io::{Reader, ReaderUtil, Writer}; use comm = core::comm; @@ -1093,7 +1091,7 @@ extern fn on_tcp_read_cb(stream: *uv::ll::uv_stream_t, log(debug, fmt!("tcp on_read_cb nread: %d", nread as int)); let reader_ch = (*socket_data_ptr).reader_ch; let buf_base = uv::ll::get_base_from_buf(buf); - let new_bytes = vec::raw::from_buf(buf_base, nread as uint); + let new_bytes = vec::from_buf(buf_base, nread as uint); core::comm::send(reader_ch, result::Ok(new_bytes)); } } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index ab24d7a53160..31ddcfafa2d6 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -233,7 +233,6 @@ fn is_exported(i: ident, m: _mod) -> bool { } } - // FIXME: glob-exports aren't supported yet. (#2006) _ => () } } From ec6311211f70ad79dee75f94fa26851f2decfcb9 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:00:08 -0700 Subject: [PATCH 122/292] Update FIXME number --- src/libsyntax/parse/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 22c25186c918..c3c182d66873 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -75,7 +75,7 @@ export parser; export CRATE_FILE; export SOURCE_FILE; -// FIXME (#1893): #ast expects to find this here but it's actually +// FIXME (#3726): #ast expects to find this here but it's actually // defined in `parse` Fixing this will be easier when we have export // decls on individual items -- then parse can export this publicly, and // everything else crate-visibly. From 72fc2b52dbbd45a2fe60fa383bbc44f8e516e281 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:06:17 -0700 Subject: [PATCH 123/292] Remove unneeded no_rt flag --- src/rustc/back/link.rs | 6 ++---- src/rustc/driver/session.rs | 22 +++++++++------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/rustc/back/link.rs b/src/rustc/back/link.rs index 2e310785306c..67edf6a32ba5 100644 --- a/src/rustc/back/link.rs +++ b/src/rustc/back/link.rs @@ -723,10 +723,8 @@ fn link_binary(sess: session, } } - if !sess.debugging_opt(session::no_rt) { - // Always want the runtime linked in - cc_args.push(~"-lrustrt"); - } + // Always want the runtime linked in + cc_args.push(~"-lrustrt"); // On linux librt and libdl are an indirect dependencies via rustrt, // and binutils 2.22+ won't add them automatically diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs index c6c0ff2826a5..e6d5c404371d 100644 --- a/src/rustc/driver/session.rs +++ b/src/rustc/driver/session.rs @@ -46,18 +46,15 @@ const trans_stats: uint = 1 << 4; const no_asm_comments: uint = 1 << 5; const no_verify: uint = 1 << 6; const trace: uint = 1 << 7; -// FIXME (#2377): This exists to transition to a Rust crate runtime -// It should be removed -const no_rt: uint = 1 << 8; -const coherence: uint = 1 << 9; -const borrowck_stats: uint = 1 << 10; -const borrowck_note_pure: uint = 1 << 11; -const borrowck_note_loan: uint = 1 << 12; -const no_landing_pads: uint = 1 << 13; -const debug_llvm: uint = 1 << 14; -const count_type_sizes: uint = 1 << 15; -const meta_stats: uint = 1 << 16; -const no_opt: uint = 1 << 17; +const coherence: uint = 1 << 8; +const borrowck_stats: uint = 1 << 9; +const borrowck_note_pure: uint = 1 << 10; +const borrowck_note_loan: uint = 1 << 11; +const no_landing_pads: uint = 1 << 12; +const debug_llvm: uint = 1 << 13; +const count_type_sizes: uint = 1 << 14; +const meta_stats: uint = 1 << 15; +const no_opt: uint = 1 << 16; fn debugging_opts_map() -> ~[(~str, ~str, uint)] { ~[(~"verbose", ~"in general, enable more debug printouts", verbose), @@ -70,7 +67,6 @@ fn debugging_opts_map() -> ~[(~str, ~str, uint)] { (~"no-asm-comments", ~"omit comments when using -S", no_asm_comments), (~"no-verify", ~"skip LLVM verification", no_verify), (~"trace", ~"emit trace logs", trace), - (~"no-rt", ~"do not link to the runtime", no_rt), (~"coherence", ~"perform coherence checking", coherence), (~"borrowck-stats", ~"gather borrowck statistics", borrowck_stats), (~"borrowck-note-pure", ~"note where purity is req'd", From fb667cde598165c83c526c945fa7ab02526dfe76 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:10:02 -0700 Subject: [PATCH 124/292] Update FIXME number --- src/rustc/front/intrinsic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs index 879c73308da8..2a87f089c8db 100644 --- a/src/rustc/front/intrinsic.rs +++ b/src/rustc/front/intrinsic.rs @@ -6,7 +6,7 @@ mod intrinsic { pub use rusti::visit_tydesc; - // FIXME (#2712): remove this when the interface has settled and the + // FIXME (#3727): remove this when the interface has settled and the // version in sys is no longer present. pub fn get_tydesc() -> *TyDesc { rusti::get_tydesc::() as *TyDesc From 63dc83198a8e2d7c1a9b43d1512b30eaa002fca8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:10:07 -0700 Subject: [PATCH 125/292] Remove obsolete FIXME --- src/rustc/metadata/decoder.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 6b8c995ffd26..689141b6bf34 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -647,7 +647,6 @@ fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc, let mth_item = lookup_item(m_did.node, cdata.data); let self_ty = get_self_ty(mth_item); rslt.push(@{did: translate_def_id(cdata, m_did), - /* FIXME (maybe #2323) tjc: take a look at this. */ n_tps: item_ty_param_count(mth_item) - base_tps, ident: item_name(intr, mth_item), self_type: self_ty}); From 3764ec7025322918acf682cda498577dffdea4d3 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:11:47 -0700 Subject: [PATCH 126/292] Remove obsolete FIXME --- src/rustc/middle/borrowck/gather_loans.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index 5dfde8c9af64..f5ac40ce93d4 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -119,12 +119,7 @@ fn req_loans_in_expr(ex: @ast::expr, let arg_cmt = self.bccx.cat_expr(*arg); self.guarantee_valid(arg_cmt, m_imm, scope_r); } - ast::by_val => { - // FIXME (#2493): safety checks would be required here, - // but the correct set is really hard to get right, - // and modes are going away anyhow. - } - ast::by_move | ast::by_copy => {} + ast::by_val | ast::by_move | ast::by_copy => {} } } visit::visit_expr(ex, self, vt); From 6986acb340f44d30438889452f5160ed2373573b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:15:12 -0700 Subject: [PATCH 127/292] Update FIXME numbers --- src/rustc/middle/const_eval.rs | 2 +- src/rustc/middle/trans/base.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rustc/middle/const_eval.rs b/src/rustc/middle/const_eval.rs index 5def18cacc31..51382b8108cf 100644 --- a/src/rustc/middle/const_eval.rs +++ b/src/rustc/middle/const_eval.rs @@ -132,7 +132,7 @@ fn classify(e: @expr, classify(base, def_map, tcx) } - // FIXME: #1272, we can probably do something CCI-ish + // FIXME: (#3728) we can probably do something CCI-ish // surrounding nonlocal constants. But we don't yet. ast::expr_path(_) => { match def_map.find(e.id) { diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 95711f8da36a..aa0f11922dd0 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -632,7 +632,7 @@ fn cast_shift_rhs(op: ast::binop, if lhs_sz < rhs_sz { trunc(rhs, lhs_llty) } else if lhs_sz > rhs_sz { - // FIXME (See discussion at #1570): If shifting by negative + // FIXME (#1877: If shifting by negative // values becomes not undefined then this is wrong. zext(rhs, lhs_llty) } else { From 66cea3700e6041bf0c7db280fc92fbb1812da724 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:18:36 -0700 Subject: [PATCH 128/292] Fix from_buf in test cases --- src/libcore/vec.rs | 4 ++-- src/libstd/uv_ll.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 5d6e8584664a..69b38c86f952 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1973,7 +1973,7 @@ mod tests { // Test on-stack copy-from-buf. let a = ~[1, 2, 3]; let mut ptr = raw::to_ptr(a); - let b = raw::from_buf(ptr, 3u); + let b = from_buf(ptr, 3u); assert (len(b) == 3u); assert (b[0] == 1); assert (b[1] == 2); @@ -1982,7 +1982,7 @@ mod tests { // Test on-heap copy-from-buf. let c = ~[1, 2, 3, 4, 5]; ptr = raw::to_ptr(c); - let d = raw::from_buf(ptr, 5u); + let d = from_buf(ptr, 5u); assert (len(d) == 5u); assert (d[0] == 1); assert (d[1] == 2); diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index f8c3882d15eb..b4b04a1a714f 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1048,7 +1048,7 @@ pub mod test { as *request_wrapper; let buf_base = get_base_from_buf(buf); let buf_len = get_len_from_buf(buf); - let bytes = vec::raw::from_buf(buf_base, buf_len as uint); + let bytes = vec::from_buf(buf_base, buf_len as uint); let read_chan = *((*client_data).read_chan); let msg_from_server = str::from_bytes(bytes); core::comm::send(read_chan, msg_from_server); @@ -1223,7 +1223,7 @@ pub mod test { buf_base as uint, buf_len as uint, nread)); - let bytes = vec::raw::from_buf(buf_base, buf_len); + let bytes = vec::from_buf(buf_base, buf_len); let request_str = str::from_bytes(bytes); let client_data = get_data_for_uv_handle( From db679a738f10953e0682e277ab85d39c3c546fd1 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:18:41 -0700 Subject: [PATCH 129/292] Remove obsolete FIXME --- src/rustc/middle/trans/datum.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/rustc/middle/trans/datum.rs b/src/rustc/middle/trans/datum.rs index 241fa5e53afb..84a3c81a9780 100644 --- a/src/rustc/middle/trans/datum.rs +++ b/src/rustc/middle/trans/datum.rs @@ -336,9 +336,6 @@ impl Datum { // This works like copy_val, except that it deinitializes the source. // Since it needs to zero out the source, src also needs to be an lval. // - // FIXME (#839): We always zero out the source. Ideally we would - // detect the case where a variable is always deinitialized by - // block exit and thus doesn't need to be dropped. fn move_to(bcx: block, action: CopyAction, dst: ValueRef) -> block { let _icx = bcx.insn_ctxt("move_to"); let mut bcx = bcx; From 41752b02b984d93f50ce6ab6a8436f876723abfe Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:42:40 -0700 Subject: [PATCH 130/292] Update FIXME numbers --- src/rustc/middle/trans/expr.rs | 2 +- src/rustc/middle/trans/foreign.rs | 2 +- src/rustc/middle/trans/tvec.rs | 2 +- src/rustc/middle/typeck/check.rs | 5 ++--- src/rustc/middle/typeck/check/method.rs | 2 +- src/rustdoc/demo.rs | 2 +- src/rustdoc/markdown_pass.rs | 5 +++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 57439daca2f2..4e50f7a848e0 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -1465,7 +1465,7 @@ fn trans_assign_op(bcx: block, // A user-defined operator method if bcx.ccx().maps.method_map.find(expr.id).is_some() { - // FIXME(#2582) evaluates the receiver twice!! + // FIXME(#2528) evaluates the receiver twice!! let scratch = scratch_datum(bcx, dst_datum.ty, false); let bcx = trans_overloaded_op(bcx, expr, dst, ~[src], SaveIn(scratch.val), DoAutorefArg); diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index 74dadd2cab49..dbf5ef810462 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -909,7 +909,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, let static_ti = get_tydesc(ccx, tp_ty); glue::lazily_emit_all_tydesc_glue(ccx, static_ti); - // FIXME (#2712): change this to T_ptr(ccx.tydesc_ty) when the + // FIXME (#3727): change this to T_ptr(ccx.tydesc_ty) when the // core::sys copy of the get_tydesc interface dies off. let td = PointerCast(bcx, static_ti.tydesc, T_ptr(T_nil())); Store(bcx, td, fcx.llretptr); diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index e1eae1156945..b78314a67478 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -466,7 +466,7 @@ fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t, let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); // Calculate the last pointer address we want to handle. - // FIXME (#2536): Optimize this when the size of the unit type is + // FIXME (#3729): Optimize this when the size of the unit type is // statically known to not use pointer casts, which tend to confuse // LLVM. let data_end_ptr = pointer_add(bcx, data_ptr, fill); diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 7cc2c8b0ad76..c1ab29758f2d 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2278,8 +2278,7 @@ fn check_enum_variants(ccx: @crate_ctxt, let cty = fcx.expr_ty(e); let declty = ty::mk_int(ccx.tcx); demand::suptype(fcx, e.span, declty, cty); - // FIXME: issue #1417 - // Also, check_expr (from check_const pass) doesn't guarantee + // check_expr (from check_const pass) doesn't guarantee // that the expression is in an form that eval_const_expr can // handle, so we may still get an internal compiler error match const_eval::eval_const_expr(ccx.tcx, e) { @@ -2620,7 +2619,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { } ~"get_tydesc" => { - // FIXME (#2712): return *intrinsic::tydesc, not *() + // FIXME (#3730): return *intrinsic::tydesc, not *() (1u, ~[], ty::mk_nil_ptr(tcx)) } ~"visit_tydesc" => { diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index f3b2c8f1b7ed..0d71d61bdaad 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -363,7 +363,7 @@ impl LookupContext { }; let method = &ms[index]; - /* FIXME(#3468) we should transform the vstore in accordance + /* FIXME(#3157) we should transform the vstore in accordance with the self type match method.self_type { diff --git a/src/rustdoc/demo.rs b/src/rustdoc/demo.rs index bf1cdf2622e4..1223f6b97232 100644 --- a/src/rustdoc/demo.rs +++ b/src/rustdoc/demo.rs @@ -7,7 +7,7 @@ * for testing purposes. It doesn't surve any functional * purpose. This here, for instance, is just some filler text. * - * FIXME (#1654): It would be nice if we could run some automated + * FIXME (#3731): It would be nice if we could run some automated * tests on this file */ diff --git a/src/rustdoc/markdown_pass.rs b/src/rustdoc/markdown_pass.rs index 924e4be63054..66c465b60215 100644 --- a/src/rustdoc/markdown_pass.rs +++ b/src/rustdoc/markdown_pass.rs @@ -84,8 +84,9 @@ fn write_markdown( doc: doc::Doc, +writer_factory: WriterFactory ) { - // FIXME #2484: There is easy parallelism to be had here but - // we don't want to spawn too many pandoc processes + // There is easy parallelism to be had here, but + // we don't want to spawn too many pandoc processes. + // (See #2484, which is closed.) do doc.pages.map |page| { let ctxt = { w: writer_factory(*page) From acaad9381d9d0ba72643f71856f9fdbb67609d81 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:42:49 -0700 Subject: [PATCH 131/292] Remove obsolete comment --- src/rustc/middle/ty.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index ca41be6f9d0a..a0366cbc0b37 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -3552,7 +3552,6 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[variant_info] { }; match variant.node.disr_expr { Some (ex) => { - // FIXME: issue #1417 disr_val = match const_eval::eval_const_expr(cx, ex) { const_eval::const_int(val) => val as int, @@ -3915,10 +3914,6 @@ fn normalize_ty(cx: ctxt, t: t) -> t { t }; - // FIXME #2187: This also reduced int types to their compatible machine - // types, which isn't necessary after #2187 - let t = mk_t(cx, mach_sty(cx.sess.targ_cfg, t)); - let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) }); let t_norm = mk_t(cx, sty); cx.normalized_cache.insert(t, t_norm); From 97c2255822a1f1a37cf625258dc7447e190fef68 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:43:39 -0700 Subject: [PATCH 132/292] Use truncate in typeck::infer; gets rid of FIXME --- src/rustc/middle/typeck/infer.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs index e5aa0debfe17..96849bf918d4 100644 --- a/src/rustc/middle/typeck/infer.rs +++ b/src/rustc/middle/typeck/infer.rs @@ -565,11 +565,8 @@ impl infer_ctxt { do indent { let r <- self.try(f); - // FIXME (#2814)---could use a vec::clear() that ran - // destructors but kept the vec at its currently allocated - // length - self.ty_var_bindings.bindings = ~[]; - self.int_var_bindings.bindings = ~[]; + self.ty_var_bindings.bindings.truncate(0); + self.int_var_bindings.bindings.truncate(0); self.region_vars.commit(); move r } From 7509a3d75b08aeaf939cea1c15be1f9f61cafdf8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:44:05 -0700 Subject: [PATCH 133/292] Remove obsolete FIXME --- src/rustc/util/common.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/rustc/util/common.rs b/src/rustc/util/common.rs index 37cc016e8ea0..e314a12a6765 100644 --- a/src/rustc/util/common.rs +++ b/src/rustc/util/common.rs @@ -87,8 +87,6 @@ fn local_rhs_span(l: @ast::local, def: span) -> span { } fn is_main_name(path: syntax::ast_map::path) -> bool { - // FIXME (#34): path should be a constrained type, so we know - // the call to last doesn't fail. vec::last(path) == syntax::ast_map::path_name( syntax::parse::token::special_idents::main ) From 915897b3df8276ea62a648c23f80b3cf1c6902b0 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 16:44:13 -0700 Subject: [PATCH 134/292] Remove obsolete comment --- src/rustc/util/ppaux.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index 0df5827ed3d8..3f8ca0f6e6a6 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -119,8 +119,6 @@ fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str { if cx.sess.verbose() {fmt!("&%u", idx)} else {~"&"} } - // FIXME(#3011) -- even if this arm is removed, exhaustiveness checking - // does not fail br_cap_avoid(id, br) => { if cx.sess.verbose() { fmt!("br_cap_avoid(%?, %s)", id, bound_region_to_str(cx, *br)) From 668b39cb5c7beafab33469e2a89dd7ac73fda23e Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:01:55 -0700 Subject: [PATCH 135/292] Use match move in pingpong, delete a FIXME --- src/test/bench/pingpong.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/test/bench/pingpong.rs b/src/test/bench/pingpong.rs index 70f98934e1bc..8aa64fed3466 100644 --- a/src/test/bench/pingpong.rs +++ b/src/test/bench/pingpong.rs @@ -41,10 +41,8 @@ macro_rules! follow ( $($message:path($($x: ident),+) -> $next:ident $e:expr)+ } => ( |m| match move m { - $(Some($message($($x,)* next)) => { - // FIXME (#2329) use regular move here once move out of - // enums is supported. - let $next = unsafe { move_it!(next) }; + $(Some($message($($x,)* move next)) => { + let $next = next; $e })+ _ => { fail } } @@ -54,10 +52,8 @@ macro_rules! follow ( $($message:path -> $next:ident $e:expr)+ } => ( |m| match move m { - $(Some($message(next)) => { - // FIXME (#2329) use regular move here once move out of - // enums is supported. - let $next = unsafe { move_it!(next) }; + $(Some($message(move next)) => { + let $next = next; $e })+ _ => { fail } } From 06d0bf7555c55dc6c9d5b9945c06d30d0edf090b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:02:12 -0700 Subject: [PATCH 136/292] Use a constant vector for the sudoku board, delete a FIXME --- src/test/bench/sudoku.rs | 45 ++++++++++++---------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 2e8ef0bac582..bd892dcb824f 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -126,40 +126,21 @@ fn write_grid(f: io::Writer, g: grid_t) { } } +const default_grid: [[u8]] = [[0, 4, 0, 6, 0, 0, 0, 7, 2, 0], //0 + [0, 0, 8, 0, 2, 0, 0, 0, 0, 0], //1 + [7, 0, 0, 8, 0, 0, 0, 0, 0, 0], //2 + [0, 0, 0, 5, 0, 0, 0, 0, 0, 0], //3 + [0, 5, 0, 0, 0, 3, 6, 0, 0, 0], //4 + [6, 8, 0, 0, 0, 0, 0, 9, 0, 0], //5 + [0, 9, 5, 0, 0, 6, 0, 7, 0, 0], //6 + [0, 0, 0, 0, 4, 0, 0, 6, 0, 0], //7 + [4, 0, 0, 0, 0, 7, 2, 0, 3, 0], //8 + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; + fn main() { let args = os::args(); - let grid = if vec::len(args) == 1u { - // FIXME create sudoku inline since nested vec consts dont work yet - // (#571) - let g = vec::from_fn(10u, |_i| { - vec::to_mut(vec::from_elem(10u, 0 as u8)) - }); - g[0][1] = 4u8; - g[0][3] = 6u8; - g[0][7] = 3u8; - g[0][8] = 2u8; - g[1][2] = 8u8; - g[1][4] = 2u8; - g[2][0] = 7u8; - g[2][3] = 8u8; - g[3][3] = 5u8; - g[4][1] = 5u8; - g[4][5] = 3u8; - g[4][6] = 6u8; - g[5][0] = 6u8; - g[5][1] = 8u8; - g[5][7] = 9u8; - g[6][1] = 9u8; - g[6][2] = 5u8; - g[6][5] = 6u8; - g[6][7] = 7u8; - g[7][4] = 4u8; - g[7][7] = 6u8; - g[8][0] = 4u8; - g[8][5] = 7u8; - g[8][6] = 2u8; - g[8][8] = 3u8; - grid_ctor(g) + let grid = if args.len() == 1 { + default_grid; } else { read_grid(io::stdin()) }; From c090dcad846f0af9cbebbed0deda5877140ed364 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:02:38 -0700 Subject: [PATCH 137/292] Uncomment nested module in test, delete a FIXME --- src/test/run-pass/item-attributes.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index a3451da6f9ac..225ba63e6a5d 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -75,7 +75,6 @@ mod test_stmt_single_attr_outer { #[attr = "val"] fn f() { } - /* FIXME: Issue #493 #[attr = "val"] mod mod1 { #[legacy_exports]; @@ -86,7 +85,6 @@ mod test_stmt_single_attr_outer { extern mod rustrt { #[legacy_exports]; } - */ } } From f1de001d69ce9394cdba7ec00dec8465955c170a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:03:02 -0700 Subject: [PATCH 138/292] Annotate FIXMEs in reflect-visit-data --- src/test/run-pass/reflect-visit-data.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index e27aaa618aca..24ae16f25e1c 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -3,13 +3,7 @@ use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor}; use libc::c_void; - -// FIXME: this is a near-duplicate of code in core::vec. -type unboxed_vec_repr = { - mut fill: uint, - mut alloc: uint, - data: u8 -}; +use vec::UnboxedVecRepr; #[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."] @@ -238,8 +232,8 @@ impl ptr_visit_adaptor: TyVisitor { } fn visit_unboxed_vec(mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::(); - // FIXME: Inner really has to move its own pointers on this one. + self.align_to::(); + // FIXME (#3732): Inner really has to move its own pointers on this one. // or else possibly we could have some weird interface wherein we // read-off a word from inner's pointers, but the read-word has to // always be the same in all sub-pointers? Dubious. @@ -570,7 +564,7 @@ impl my_visitor: TyVisitor { fn visit_enter_enum(_n_variants: uint, _sz: uint, _align: uint) -> bool { - // FIXME: this needs to rewind between enum variants, or something. + // FIXME (#3732): this needs to rewind between enum variants, or something. true } fn visit_enter_enum_variant(_variant: uint, From b24cba877dc9d7f825c46d04c5dc3a4e6cb7735c Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:03:29 -0700 Subject: [PATCH 139/292] Un-XFAIL reflect-visit-type --- src/test/run-pass/reflect-visit-type.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index f7eb2c013155..e7f2b536601e 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -1,6 +1,3 @@ -// FIXME: un-xfail after snapshot -// xfail-test - use intrinsic::{tydesc, get_tydesc, visit_tydesc, ty_visitor}; enum my_visitor = @{ mut types: ~[str] }; From 5a849ea8adb32863a588132e2bbe1eb60e966bb0 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:03:48 -0700 Subject: [PATCH 140/292] Use match move in select-macro, get rid of a FIXME --- src/test/run-pass/select-macro.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/run-pass/select-macro.rs b/src/test/run-pass/select-macro.rs index 78bddffcc1d4..4c395ae85a36 100644 --- a/src/test/run-pass/select-macro.rs +++ b/src/test/run-pass/select-macro.rs @@ -26,9 +26,8 @@ macro_rules! select_if ( } => { if $index == $count { match move pipes::try_recv($port) { - $(Some($message($($(ref $x,)+)* ref next)) => { - // FIXME (#2329) we really want move out of enum here. - let $next = unsafe { let x <- *ptr::addr_of(&(*next)); x }; + $(Some($message($($(ref $x,)+)* move next)) => { + let $next = next; $e })+ _ => fail From 3c1ff31f4a70b6bd7840cf75af9395aedfac060b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:03:56 -0700 Subject: [PATCH 141/292] Un-XFAIL task-compare --- src/test/run-pass/task-compare.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/run-pass/task-compare.rs b/src/test/run-pass/task-compare.rs index 652d131584f7..2c51e5d3e666 100644 --- a/src/test/run-pass/task-compare.rs +++ b/src/test/run-pass/task-compare.rs @@ -2,9 +2,6 @@ A test case for issue #577, which also exposes #588 */ -// FIXME: This won't work until we can compare resources (#2601) -// xfail-test - extern mod std; use task::join; From 945d57a6ff8d31337bf6cdedcfa6c4a03d9f1ddc Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:58:45 -0700 Subject: [PATCH 142/292] Export VecUnboxedRepr from vec so a test case can use it --- src/libcore/reflect.rs | 2 +- src/libcore/repr.rs | 5 +++-- src/libcore/vec.rs | 14 +++++++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index 505804b3da82..3fa37a2fb8e5 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -246,7 +246,7 @@ impl MovePtrAdaptor: TyVisitor { } fn visit_unboxed_vec(mtbl: uint, inner: *TyDesc) -> bool { - self.align_to::(); + self.align_to::(); if ! self.inner.visit_vec(mtbl, inner) { return false; } true } diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 0501b032d2d5..2003949d6314 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -15,7 +15,8 @@ use to_str::ToStr; use cast::transmute; use intrinsic::{TyDesc, TyVisitor, visit_tydesc}; use reflect::{MovePtr, MovePtrAdaptor}; -use vec::raw::{VecRepr, UnboxedVecRepr, SliceRepr}; +use vec::UnboxedVecRepr; +use vec::raw::{VecRepr, SliceRepr}; pub use box::raw::BoxRepr; use box::raw::BoxHeaderRepr; @@ -303,7 +304,7 @@ impl ReprVisitor : TyVisitor { fn visit_unboxed_vec(mtbl: uint, inner: *TyDesc) -> bool { - do self.get:: |b| { + do self.get:: |b| { self.write_unboxed_vec_repr(mtbl, b, inner); } } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 69b38c86f952..b242ed5aee4f 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1671,6 +1671,13 @@ pub unsafe fn from_buf(ptr: *T, elts: uint) -> ~[T] { raw::from_buf_raw(ptr, elts) } +/// The internal 'unboxed' representation of a vector +pub struct UnboxedVecRepr { + mut fill: uint, + mut alloc: uint, + data: u8 +} + /// Unsafe operations mod raw { @@ -1680,13 +1687,6 @@ mod raw { unboxed: UnboxedVecRepr } - /// The internal 'unboxed' representation of a vector - pub struct UnboxedVecRepr { - mut fill: uint, - mut alloc: uint, - data: u8 - } - pub type SliceRepr = { mut data: *u8, mut len: uint From dd54431df68202f5debffd139121851ec1da9428 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:59:14 -0700 Subject: [PATCH 143/292] Fix pipe-select-macro --- src/test/run-pass/pipe-select-macro.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-pass/pipe-select-macro.rs b/src/test/run-pass/pipe-select-macro.rs index 8554659a2eeb..bc99ac788e0e 100644 --- a/src/test/run-pass/pipe-select-macro.rs +++ b/src/test/run-pass/pipe-select-macro.rs @@ -42,7 +42,7 @@ fn test(+foo: foo::client::foo, +bar: bar::client::bar) { }, do_baz(b) -> _next { - if *b { debug!("true") } else { debug!("false") } + if b { debug!("true") } else { debug!("false") } } } ) From 2d116db57808599fbc6ba1e278e410e4a3c24a62 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:59:29 -0700 Subject: [PATCH 144/292] Use move instead of ref in select-macro --- src/test/run-pass/select-macro.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-pass/select-macro.rs b/src/test/run-pass/select-macro.rs index 4c395ae85a36..517c61266d9c 100644 --- a/src/test/run-pass/select-macro.rs +++ b/src/test/run-pass/select-macro.rs @@ -26,7 +26,7 @@ macro_rules! select_if ( } => { if $index == $count { match move pipes::try_recv($port) { - $(Some($message($($(ref $x,)+)* move next)) => { + $(Some($message($($(move $x,)+)* move next)) => { let $next = next; $e })+ From 55b528484d1b705626335b94080e67af3437b421 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 17:59:33 -0700 Subject: [PATCH 145/292] Re-xfail two tests that I tried to resurrect (no time right now) --- src/test/run-pass/reflect-visit-type.rs | 61 +++++++++++++------------ src/test/run-pass/task-compare.rs | 54 +++++++++++++++++++--- 2 files changed, 78 insertions(+), 37 deletions(-) diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index e7f2b536601e..4d2d2a7170e0 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -1,34 +1,35 @@ -use intrinsic::{tydesc, get_tydesc, visit_tydesc, ty_visitor}; +// xfail-test +use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor}; enum my_visitor = @{ mut types: ~[str] }; -impl of ty_visitor for my_visitor { +impl my_visitor: TyVisitor { fn visit_bot() -> bool { - self.types += ["bot"]; + self.types += ~["bot"]; error!("visited bot type"); true } fn visit_nil() -> bool { - self.types += ["nil"]; + self.types += ~["nil"]; error!("visited nil type"); true } fn visit_bool() -> bool { - self.types += ["bool"]; + self.types += ~["bool"]; error!("visited bool type"); true } fn visit_int() -> bool { - self.types += ["int"]; + self.types += ~["int"]; error!("visited int type"); true } fn visit_i8() -> bool { - self.types += ["i8"]; + self.types += ~["i8"]; error!("visited i8 type"); true } fn visit_i16() -> bool { - self.types += ["i16"]; + self.types += ~["i16"]; error!("visited i16 type"); true } @@ -54,41 +55,41 @@ impl of ty_visitor for my_visitor { fn visit_estr_fixed(_sz: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_box(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_uniq(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_ptr(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_rptr(_mtbl: uint, _inner: *tydesc) -> bool { true } + fn visit_box(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_uniq(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_ptr(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_rptr(_mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_vec(_mtbl: uint, inner: *tydesc) -> bool { - self.types += ["["]; - visit_tydesc(inner, my_visitor(*self) as ty_visitor); - self.types += ["]"]; + fn visit_vec(_mtbl: uint, inner: *TyDesc) -> bool { + self.types += ~["["]; + visit_tydesc(inner, my_visitor(*self) as TyVisitor); + self.types += ~["]"]; true } - fn visit_unboxed_vec(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_evec_box(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_evec_uniq(_mtbl: uint, _inner: *tydesc) -> bool { true } - fn visit_evec_slice(_mtbl: uint, _inner: *tydesc) -> bool { true } + fn visit_unboxed_vec(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_box(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_uniq(_mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_slice(_mtbl: uint, _inner: *TyDesc) -> bool { true } fn visit_evec_fixed(_n: uint, _sz: uint, _align: uint, - _mtbl: uint, _inner: *tydesc) -> bool { true } + _mtbl: uint, _inner: *TyDesc) -> bool { true } fn visit_enter_rec(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } fn visit_rec_field(_i: uint, _name: &str, - _mtbl: uint, _inner: *tydesc) -> bool { true } + _mtbl: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_rec(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } fn visit_enter_class(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } fn visit_class_field(_i: uint, _name: &str, - _mtbl: uint, _inner: *tydesc) -> bool { true } + _mtbl: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_class(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } fn visit_enter_tup(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_tup_field(_i: uint, _inner: *tydesc) -> bool { true } + fn visit_tup_field(_i: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_tup(_n_fields: uint, _sz: uint, _align: uint) -> bool { true } @@ -98,7 +99,7 @@ impl of ty_visitor for my_visitor { _disr_val: int, _n_fields: uint, _name: &str) -> bool { true } - fn visit_enum_variant_field(_i: uint, _inner: *tydesc) -> bool { true } + fn visit_enum_variant_field(_i: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_enum_variant(_variant: uint, _disr_val: int, _n_fields: uint, @@ -108,8 +109,8 @@ impl of ty_visitor for my_visitor { fn visit_enter_fn(_purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_fn_input(_i: uint, _mode: uint, _inner: *tydesc) -> bool { true } - fn visit_fn_output(_retstyle: uint, _inner: *tydesc) -> bool { true } + fn visit_fn_input(_i: uint, _mode: uint, _inner: *TyDesc) -> bool { true } + fn visit_fn_output(_retstyle: uint, _inner: *TyDesc) -> bool { true } fn visit_leave_fn(_purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } @@ -121,17 +122,17 @@ impl of ty_visitor for my_visitor { fn visit_self() -> bool { true } fn visit_type() -> bool { true } fn visit_opaque_box() -> bool { true } - fn visit_constr(_inner: *tydesc) -> bool { true } + fn visit_constr(_inner: *TyDesc) -> bool { true } fn visit_closure_ptr(_ck: uint) -> bool { true } } -fn visit_ty(v: ty_visitor) { +fn visit_ty(v: TyVisitor) { visit_tydesc(get_tydesc::(), v); } fn main() { let v = my_visitor(@{mut types: ~[]}); - let vv = v as ty_visitor; + let vv = v as TyVisitor; visit_ty::(vv); visit_ty::(vv); diff --git a/src/test/run-pass/task-compare.rs b/src/test/run-pass/task-compare.rs index 2c51e5d3e666..4b5852a1d972 100644 --- a/src/test/run-pass/task-compare.rs +++ b/src/test/run-pass/task-compare.rs @@ -1,20 +1,60 @@ +// xfail-test /** A test case for issue #577, which also exposes #588 */ extern mod std; -use task::join; fn child() { } +struct notify { + ch: comm::Chan, v: @mut bool, + drop { + error!("notify: task=%? v=%x unwinding=%b b=%b", + task::get_task(), + ptr::addr_of(&(*(self.v))) as uint, + task::failing(), + *(self.v)); + let b = *(self.v); + comm::send(self.ch, b); + } +} + +fn notify(ch: comm::Chan, v: @mut bool) -> notify { + notify { + ch: ch, + v: v + } +} + +fn joinable(+f: fn~()) -> comm::Port { + fn wrapper(+c: comm::Chan, +f: fn()) { + let b = @mut false; + error!("wrapper: task=%? allocated v=%x", + task::get_task(), + ptr::addr_of(&(*b)) as uint); + let _r = notify(c, b); + f(); + *b = true; + } + let p = comm::Port(); + let c = comm::Chan(&p); + do task::spawn_unlinked { wrapper(c, copy f) }; + p +} + +fn join(port: comm::Port) -> bool { + comm::recv(port) +} + fn main() { // tasks let t1; let t2; let c1 = child, c2 = child; - t1 = task::spawn_joinable(c1); - t2 = task::spawn_joinable(c2); + t1 = joinable(c1); + t2 = joinable(c2); assert (t1 == t1); assert (t1 != t2); @@ -23,15 +63,15 @@ fn main() { let p1; let p2; - p1 = comm::port::(); - p2 = comm::port::(); + p1 = comm::Port::(); + p2 = comm::Port::(); assert (p1 == p1); assert (p1 != p2); // channels - let c1 = comm::chan(p1); - let c2 = comm::chan(p2); + let c1 = comm::Chan(p1); + let c2 = comm::Chan(p2); assert (c1 == c1); assert (c1 != c2); From 44bffd2059d55a536ccaac4ff1bd67ecb4297896 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 18:08:58 -0700 Subject: [PATCH 146/292] Revert "Use a constant vector for the sudoku board, delete a FIXME" This reverts commit 06d0bf7555c55dc6c9d5b9945c06d30d0edf090b. --- src/test/bench/sudoku.rs | 45 ++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index bd892dcb824f..2e8ef0bac582 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -126,21 +126,40 @@ fn write_grid(f: io::Writer, g: grid_t) { } } -const default_grid: [[u8]] = [[0, 4, 0, 6, 0, 0, 0, 7, 2, 0], //0 - [0, 0, 8, 0, 2, 0, 0, 0, 0, 0], //1 - [7, 0, 0, 8, 0, 0, 0, 0, 0, 0], //2 - [0, 0, 0, 5, 0, 0, 0, 0, 0, 0], //3 - [0, 5, 0, 0, 0, 3, 6, 0, 0, 0], //4 - [6, 8, 0, 0, 0, 0, 0, 9, 0, 0], //5 - [0, 9, 5, 0, 0, 6, 0, 7, 0, 0], //6 - [0, 0, 0, 0, 4, 0, 0, 6, 0, 0], //7 - [4, 0, 0, 0, 0, 7, 2, 0, 3, 0], //8 - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; - fn main() { let args = os::args(); - let grid = if args.len() == 1 { - default_grid; + let grid = if vec::len(args) == 1u { + // FIXME create sudoku inline since nested vec consts dont work yet + // (#571) + let g = vec::from_fn(10u, |_i| { + vec::to_mut(vec::from_elem(10u, 0 as u8)) + }); + g[0][1] = 4u8; + g[0][3] = 6u8; + g[0][7] = 3u8; + g[0][8] = 2u8; + g[1][2] = 8u8; + g[1][4] = 2u8; + g[2][0] = 7u8; + g[2][3] = 8u8; + g[3][3] = 5u8; + g[4][1] = 5u8; + g[4][5] = 3u8; + g[4][6] = 6u8; + g[5][0] = 6u8; + g[5][1] = 8u8; + g[5][7] = 9u8; + g[6][1] = 9u8; + g[6][2] = 5u8; + g[6][5] = 6u8; + g[6][7] = 7u8; + g[7][4] = 4u8; + g[7][7] = 6u8; + g[8][0] = 4u8; + g[8][5] = 7u8; + g[8][6] = 2u8; + g[8][8] = 3u8; + grid_ctor(g) } else { read_grid(io::stdin()) }; From 693866d75e25425053c61dc16adcc12b977d86f0 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 18:09:55 -0700 Subject: [PATCH 147/292] Change FIXME number --- src/test/bench/sudoku.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 2e8ef0bac582..921aa8f0657f 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -130,7 +130,7 @@ fn main() { let args = os::args(); let grid = if vec::len(args) == 1u { // FIXME create sudoku inline since nested vec consts dont work yet - // (#571) + // (#3733) let g = vec::from_fn(10u, |_i| { vec::to_mut(vec::from_elem(10u, 0 as u8)) }); From fd85a0000a542a52f0fda3bd2f941fba452e0698 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 15:46:16 -0700 Subject: [PATCH 148/292] manual: add section on do-expressions. --- doc/rust.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/doc/rust.md b/doc/rust.md index 628cb1370613..1dfeaddc1a2b 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2071,6 +2071,52 @@ the loop. A `loop` expression is only permitted in the body of a loop. +### Do expressions + +~~~~~~~~{.ebnf .gram} +do_expr : "do" expr [ '|' ident_list '|' ] ? '{' block '}' ; +~~~~~~~~ + +A _do expression_ provides a more-familiar block-syntax for a [lambda expression](#lambda-expressions), +including a special translation of [return expressions](#return-expressions) inside the supplied block. + +The optional `ident_list` and `block` provided in a `do` expression are parsed as though they constitute a lambda expression; +if the `ident_list` is missing, an empty `ident_list` is implied. + +The lambda expression is then provided as a _trailing argument_ +to the outermost [call](#call-expressions) or [method call](#method-call-expressions) expression +in the `expr` following `do`. +If the `expr` is a [path expression](#path-expressions), it is parsed as though it is a call expression. +If the `expr` is a [field expression](#field-expressions), it is parsed as though it is a method call expression. + +Additionally, any occurrence of a [return expression](#return-expressions) +inside the `block` of a `do` expression is rewritten +as a reference to an (anonymous) flag set in the caller's environment, +which is checked on return from the `expr` and, if set, +causes a corresponding return from the caller. +In this way, the meaning of `return` statements in language built-in control blocks is preserved, +if they are rewritten using lambda functions and `do` expressions as abstractions. + +Therefore the two calls to `f` in this example are equivalent. +Both cause an early return from the caller's frame: + +~~~~ +# fn f(f: fn(int)) { } +# fn g(i: int) { } + +{ + let mut _early_ret = false; + f(|j| { g(j); _early_ret = true; }); + if early_ret { return; } +} + +do f |j| { + g(j); + return; +} +~~~~ + + ### For expressions ~~~~~~~~{.ebnf .gram} From 515f88f1c1ca5638c0ed0f64b7c17add45ae5db3 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 17:08:48 -0700 Subject: [PATCH 149/292] manual: rewrite for-expression section to reflect this year's definition. --- doc/rust.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 1dfeaddc1a2b..a4ca7fbefced 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2120,13 +2120,21 @@ do f |j| { ### For expressions ~~~~~~~~{.ebnf .gram} -for_expr : "for" pat "in" expr '{' block '}' ; +for_expr : "for" expr [ '|' ident_list '|' ] ? '{' block '}' ; ~~~~~~~~ -A _for loop_ is controlled by a vector or string. The for loop bounds-checks -the underlying sequence *once* when initiating the loop, then repeatedly -executes the loop body with the loop variable referencing the successive -elements of the underlying sequence, one iteration per sequence element. +A _for expression_ is similar to a [`do` expression](#do-expressions), +in that it provides a special block-form of lambda expression, +suited to passing the `block` function to a higher-order function implementing a loop. + +Like a `do` expression, a `return` expression inside a `for` expresison is rewritten, +to access a local flag that causes an early return in the caller. + +Additionally, [`break`](#break-expressions) and [`loop`](#loop-expressions) expressions +are rewritten inside `for` expressions, with a combination of local flag variables, +and early boolean-valued returns from the `block` function, +such that the meaning of `break` and `loop` is preserved in a primitive loop +when rewritten as a `for` loop controlled by a higher order function. An example a for loop: @@ -2135,7 +2143,7 @@ An example a for loop: # fn bar(f: foo) { } # let a = 0, b = 0, c = 0; -let v: ~[foo] = ~[a, b, c]; +let v: [foo] = [a, b, c]; for v.each |e| { bar(*e); From 1d69b81eef098732ea7e3b4062bdcf33710c8033 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 17:15:00 -0700 Subject: [PATCH 150/292] manual: "to" -> ".." --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index a4ca7fbefced..ce1caacf2214 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2180,7 +2180,7 @@ match_expr : "match" expr '{' match_arm [ '|' match_arm ] * '}' ; match_arm : match_pat '=>' expr_or_blockish ; -match_pat : pat [ "to" pat ] ? [ "if" expr ] ; +match_pat : pat [ ".." pat ] ? [ "if" expr ] ; ~~~~~~~~ From 533cce80504b5cc6d29b1d2d3e0dfc0d77095702 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 17:16:16 -0700 Subject: [PATCH 151/292] manual: remove unusual production name in match-expr grammar. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index ce1caacf2214..ee1d581d0250 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2178,7 +2178,7 @@ then any `else` block is executed. ~~~~~~~~{.ebnf .gram} match_expr : "match" expr '{' match_arm [ '|' match_arm ] * '}' ; -match_arm : match_pat '=>' expr_or_blockish ; +match_arm : match_pat '=>' [ expr "," | '{' block '}' ] ; match_pat : pat [ ".." pat ] ? [ "if" expr ] ; ~~~~~~~~ From 544d36bc4d186f54e887ea427c377d806c2e73fe Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 17:49:54 -0700 Subject: [PATCH 152/292] manual: fixes to match expression examples and explanation. --- doc/rust.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index ee1d581d0250..8e8a01715217 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2186,7 +2186,7 @@ match_pat : pat [ ".." pat ] ? [ "if" expr ] ; A `match` expression branches on a *pattern*. The exact form of matching that occurs depends on the pattern. Patterns consist of some combination of -literals, destructured enum constructors, records and tuples, variable binding +literals, destructured enum constructors, structures, records and tuples, variable binding specifications, wildcards (`*`), and placeholders (`_`). A `match` expression has a *head expression*, which is the value to compare to the patterns. The type of the patterns must equal the type of the head expression. @@ -2196,19 +2196,19 @@ In a pattern whose head expression has an `enum` type, a placeholder (`_`) stand variant. For example: ~~~~ -enum list { nil, cons(X, @list) } +enum List { Nil, Cons(X, @List) } -let x: list = cons(10, @cons(11, @nil)); +let x: List = Cons(10, @Cons(11, @Nil)); match x { - cons(_, @nil) => fail ~"singleton list", - cons(*) => return, - nil => fail ~"empty list" + Cons(_, @Nil) => fail ~"singleton list", + Cons(*) => return, + Nil => fail ~"empty list" } ~~~~ -The first pattern matches lists constructed by applying `cons` to any head value, and a -tail value of `@nil`. The second pattern matches `any` list constructed with `cons`, +The first pattern matches lists constructed by applying `Cons` to any head value, and a +tail value of `@Nil`. The second pattern matches _any_ list constructed with `Cons`, ignoring the values of its arguments. The difference between `_` and `*` is that the pattern `C(_)` is only type-correct if `C` has exactly one argument, while the pattern `C(*)` is type-correct for any enum variant `C`, regardless of how many arguments `C` has. @@ -2225,18 +2225,18 @@ An example of an `match` expression: # fn process_pair(a: int, b: int) { } # fn process_ten() { } -enum list { nil, cons(X, @list) } +enum List { Nil, Cons(X, @List) } -let x: list = cons(10, @cons(11, @nil)); +let x: List = Cons(10, @Cons(11, @Nil)); match x { - cons(a, @cons(b, _)) => { + Cons(a, @Cons(b, _)) => { process_pair(a,b); } - cons(10, _) => { + Cons(10, _) => { process_ten(); } - nil => { + Nil => { return; } _ => { @@ -2245,7 +2245,7 @@ match x { } ~~~~ -Records can also be pattern-matched and their fields bound to variables. +Records and structures can also be pattern-matched and their fields bound to variables. When matching fields of a record, the fields being matched are specified first, then a placeholder (`_`) represents the remaining fields. From 73d4417dc75b32d3a22f1a747afa3afea6e52252 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 17:50:10 -0700 Subject: [PATCH 153/292] manual: remove 'analogy' between return and return. meaningless. --- doc/rust.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 8e8a01715217..44a6121751af 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2330,8 +2330,7 @@ return_expr : "return" expr ? ; ~~~~~~~~ Return expressions are denoted with the keyword `return`. Evaluating a `return` -expression^[A `return` expression is analogous to a `return` expression -in the C family.] moves its argument into the output slot of the current +expression moves its argument into the output slot of the current function, destroys the current function activation frame, and transfers control to the caller frame. From a1c831be25100672d1ab8757bac90748ce935bcd Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 17:50:44 -0700 Subject: [PATCH 154/292] manual: avoid describing 'assert' as 'like check', note future removal. --- doc/rust.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 44a6121751af..372f87ff0f8c 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2404,11 +2404,10 @@ It is therefore recommended to use the macro forms of logging (`error!`, `debug! assert_expr : "assert" expr ; ~~~~~~~~ -An `assert` expression is similar to a `check` expression, except -the condition may be any boolean-typed expression, and the compiler makes no -use of the knowledge that the condition holds if the program continues to -execute after the `assert`. +> **Note:** In future versions of Rust, `assert` will be changed from a full expression to a macro. +An `assert` expression causes the program to fail if its `expr` argument evaluates to `false`. +The failure carries string representation of the false expression. # Type system From 196cc0265cd1d998ce93c9ff216b896cc4ba648a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 17:51:15 -0700 Subject: [PATCH 155/292] manual: add 'item', remove statement that built-in types are keywords. --- doc/rust.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 372f87ff0f8c..19ecefe85275 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2413,14 +2413,12 @@ The failure carries string representation of the false expression. ## Types -Every slot and value in a Rust program has a type. The _type_ of a *value* +Every slot, item and value in a Rust program has a type. The _type_ of a *value* defines the interpretation of the memory holding it. Built-in types and type-constructors are tightly integrated into the language, in nontrivial ways that are not possible to emulate in user-defined -types. User-defined types have limited capabilities. In addition, every -built-in type or type-constructor name is reserved as a *keyword* in Rust; -they cannot be used as user-defined identifiers in any context. +types. User-defined types have limited capabilities. ### Primitive types From 45dc69d887867d5ef1c6e8632bb6db1c786ffe56 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 17:52:12 -0700 Subject: [PATCH 156/292] manual: example fixup. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 19ecefe85275..e6c1c9525b5c 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2107,7 +2107,7 @@ Both cause an early return from the caller's frame: { let mut _early_ret = false; f(|j| { g(j); _early_ret = true; }); - if early_ret { return; } + if _early_ret { return; } } do f |j| { From 9ea5e6a3b26213a64db3bd14ec3f74523d8f1d62 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 18:05:05 -0700 Subject: [PATCH 157/292] manual: fix vec and str types to discuss definite / indefinite size. --- doc/rust.md | 47 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index e6c1c9525b5c..88e3bd2125f0 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2478,13 +2478,16 @@ type `float` may not be equal to the largest *supported* floating-point type. ### Textual types -The types `char` and `~str` hold textual data. +The types `char` and `str` hold textual data. A value of type `char` is a Unicode character, represented as a 32-bit unsigned word holding a UCS-4 codepoint. -A value of type `~str` is a Unicode string, represented as a vector of 8-bit +A value of type `str` is a Unicode string, represented as a vector of 8-bit unsigned bytes holding a sequence of UTF-8 codepoints. +Since `str` is of indefinite size, it is not a _first class_ type, +but can only be instantiated through a pointer type, +such as `&str`, `@str` or `~str`. ### Tuple types @@ -2505,45 +2508,35 @@ order specified by the tuple type. An example of a tuple type and its use: ~~~~ -type pair = (int,~str); -let p: pair = (10,~"hello"); +type Pair = (int,&str); +let p: Pair = (10,"hello"); let (a, b) = p; -assert b != ~"world"; +assert b != "world"; ~~~~ ### Vector types -The vector type-constructor represents a homogeneous array of values of a -given type. A vector has a fixed size. The kind of a vector type depends on -the kind of its member type, as with other simple structural types. +The vector type-constructor represents a homogeneous array of values of a given type. +A vector has a fixed size. +A vector type can be accompanied by _definite_ size, written with a trailing asterisk and integer literal, such as `[int * 10]`. +Such a definite-sized vector can be treated as a first class type since its size is known statically. +A vector without such a size is said to be of _indefinite_ size, +and is therefore not a _first class_ type, +can only be instantiated through a pointer type, +such as `&[T]`, `@[T]` or `~[T]`. +The kind of a vector type depends on the kind of its member type, as with other simple structural types. An example of a vector type and its use: ~~~~ -let v: ~[int] = ~[7, 5, 3]; +let v: &[int] = [7, 5, 3]; let i: int = v[2]; assert (i == 3); ~~~~ -Vectors always *allocate* a storage region sufficient to store the first power -of two worth of elements greater than or equal to the size of the vector. This -behaviour supports idiomatic in-place "growth" of a mutable slot holding a -vector: - - -~~~~ -let mut v: ~[int] = ~[1, 2, 3]; -v += ~[4, 5, 6]; -~~~~ - -Normal vector concatenation causes the allocation of a fresh vector to hold -the result; in this case, however, the slot holding the vector recycles the -underlying storage in-place (since the reference-count of the underlying -storage is equal to 1). - -All accessible elements of a vector are always initialized, and access to a -vector is always bounds-checked. +All accessible elements of a vector are always initialized, and access to a vector is always bounds-checked. +In the case of a definite- ### Structure types From 089e257769a3f46fe8cc0668bebe602a9209d334 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 18:07:50 -0700 Subject: [PATCH 158/292] manual: capitalize more examples properly. --- doc/rust.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 88e3bd2125f0..eab1e04c92a0 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2686,8 +2686,8 @@ fn add(x: int, y: int) -> int { let mut x = add(5,7); -type binop = fn(int,int) -> int; -let bo: binop = add; +type Binop = fn(int,int) -> int; +let bo: Binop = add; x = bo(5,7); ~~~~~~~~ @@ -2697,24 +2697,24 @@ Every trait item (see [traits](#traits)) defines a type with the same name as the trait. For a trait `T`, cast expressions introduce values of type `T`: ~~~~~~~~ -trait printable { +trait Printable { fn to_str() -> ~str; } -impl ~str: printable { +impl ~str: Printable { fn to_str() -> ~str { self } } -fn print(a: printable) { +fn print(a: Printable) { io::println(a.to_str()); } fn main() { - print(~"meow" as printable); + print(~"meow" as ~Printable); } ~~~~~~~~ -In this example, the trait `printable` occurs as a type in both the type signature of +In this example, the trait `Printable` occurs as a type in both the type signature of `print`, and the cast expression in `main`. ### Type parameters @@ -2740,16 +2740,16 @@ impl item. It refers to the type of the implicit `self` argument. For example, in: ~~~~~~ -trait printable { +trait Printable { fn to_str() -> ~str; } -impl ~str: printable { +impl ~str: Printable { fn to_str() -> ~str { self } } ~~~~~~ -`self` refers to the value of type `str` that is the receiver for a +`self` refers to the value of type `~str` that is the receiver for a call to the method `to_str`. ## Type kinds From 9bbff50c14c34d7c0c02f8062747bfedf3d21cd3 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 18:18:37 -0700 Subject: [PATCH 159/292] manual: fix various examples. --- doc/rust.md | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index eab1e04c92a0..83b78b398838 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2089,30 +2089,16 @@ in the `expr` following `do`. If the `expr` is a [path expression](#path-expressions), it is parsed as though it is a call expression. If the `expr` is a [field expression](#field-expressions), it is parsed as though it is a method call expression. -Additionally, any occurrence of a [return expression](#return-expressions) -inside the `block` of a `do` expression is rewritten -as a reference to an (anonymous) flag set in the caller's environment, -which is checked on return from the `expr` and, if set, -causes a corresponding return from the caller. -In this way, the meaning of `return` statements in language built-in control blocks is preserved, -if they are rewritten using lambda functions and `do` expressions as abstractions. - -Therefore the two calls to `f` in this example are equivalent. -Both cause an early return from the caller's frame: +In this example, both calls to `f` are equivalent: ~~~~ # fn f(f: fn(int)) { } # fn g(i: int) { } -{ - let mut _early_ret = false; - f(|j| { g(j); _early_ret = true; }); - if _early_ret { return; } -} +f(|j| g(j)); do f |j| { g(j); - return; } ~~~~ @@ -2130,7 +2116,15 @@ suited to passing the `block` function to a higher-order function implementing a Like a `do` expression, a `return` expression inside a `for` expresison is rewritten, to access a local flag that causes an early return in the caller. -Additionally, [`break`](#break-expressions) and [`loop`](#loop-expressions) expressions +Additionally, any occurrence of a [return expression](#return-expressions) +inside the `block` of a `for` expression is rewritten +as a reference to an (anonymous) flag set in the caller's environment, +which is checked on return from the `expr` and, if set, +causes a corresponding return from the caller. +In this way, the meaning of `return` statements in language built-in control blocks is preserved, +if they are rewritten using lambda functions and `do` expressions as abstractions. + +Like `return` expressions, any [`break`](#break-expressions) and [`loop`](#loop-expressions) expressions are rewritten inside `for` expressions, with a combination of local flag variables, and early boolean-valued returns from the `block` function, such that the meaning of `break` and `loop` is preserved in a primitive loop @@ -2143,7 +2137,7 @@ An example a for loop: # fn bar(f: foo) { } # let a = 0, b = 0, c = 0; -let v: [foo] = [a, b, c]; +let v: &[foo] = &[a, b, c]; for v.each |e| { bar(*e); @@ -2530,7 +2524,7 @@ The kind of a vector type depends on the kind of its member type, as with other An example of a vector type and its use: ~~~~ -let v: &[int] = [7, 5, 3]; +let v: &[int] = &[7, 5, 3]; let i: int = v[2]; assert (i == 3); ~~~~ @@ -2701,16 +2695,16 @@ trait Printable { fn to_str() -> ~str; } -impl ~str: Printable { - fn to_str() -> ~str { self } +impl int: Printable { + fn to_str() -> ~str { int::to_str(self, 10) } } -fn print(a: Printable) { +fn print(a: @Printable) { io::println(a.to_str()); } fn main() { - print(~"meow" as ~Printable); + print(@10 as @Printable); } ~~~~~~~~ From 70909533f09a6d187b7728f970a64c448c79290c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 19:07:38 -0700 Subject: [PATCH 160/292] manual: rewrite the section on type kinds. --- doc/rust.md | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 83b78b398838..dc247afc3d36 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2748,40 +2748,45 @@ call to the method `to_str`. ## Type kinds -Types in Rust are categorized into three kinds, based on whether they -allow copying of their values, and sending to different tasks. The -kinds are: +Types in Rust are categorized into kinds, based on various properties of the components of the type. +The kinds are: -Sendable - : Values with a sendable type can be safely sent to another task. +`Const` + : Types of this kind are deeply immutable; + they contain no mutable memory locations directly or indirectly via pointers. +`Send` + : Types of this kind can be safely sent between tasks. This kind includes scalars, owning pointers, owned closures, and structural types containing only other sendable types. -Copyable +`Owned` + : Types of this kind do not contain any borrowed pointers; + this can be a useful guarantee for code that breaks borrowing assumptions using [`unsafe` operations](#unsafe-functions). +`Copy` : This kind includes all types that can be copied. All types with sendable kind are copyable, as are managed boxes, managed closures, trait types, and structural types built out of these. -Noncopyable - : [Resource](#resources) types, and every type that includes a - resource without storing it in a managed box, may not be copied. - Types of sendable or copyable type can always be used in places - where a noncopyable type is expected, so in effect this kind - includes all types. +_Default_ + : Types with destructors, closure environments, + and various other _non-first-class_ types, + are not copyable at all. + Such types can usually only be accessed through pointers, + or in some cases, moved between mutable locations. -These form a hierarchy. The noncopyable kind is the widest, including -all types in the language. The copyable kind is a subset of that, and -the sendable kind is a subset of the copyable kind. +Kinds can be supplied as _bounds_ on type parameters, like traits, +in which case the parameter is constrained to types satisfying that kind. -Any operation that causes a value to be copied requires the type of -that value to be of copyable kind. Type parameter types are assumed to -be noncopyable, unless one of the special bounds `send` or `copy` is -declared for it. For example, this is not a valid program: +By default, type parameters do not carry any assumed kind-bounds at all. + +Any operation that causes a value to be copied requires the type of that value to be of copyable kind, +so the `Copy` bound is frequently required on function type parameters. +For example, this is not a valid program: ~~~~{.xfail-test} fn box(x: T) -> @T { @x } ~~~~ -Putting `x` into a managed box involves copying, and the `T` parameter -is assumed to be noncopyable. To change that, a bound is declared: +Putting `x` into a managed box involves copying, and the `T` parameter has the default (non-copyable) kind. +To change that, a bound is declared: ~~~~ fn box(x: T) -> @T { @x } From d471e2421411d86a56d88bfc3ed78b391b8b809f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 19:12:35 -0700 Subject: [PATCH 161/292] manual: remove description of references (modes) from memory-slots section. --- doc/rust.md | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index dc247afc3d36..1f546c53ffbc 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2870,16 +2870,12 @@ references to any boxes; the remainder of its heap is immediately freed. A task's stack contains slots. -A _slot_ is a component of a stack frame. A slot is either a *local variable* -or a *reference*. +A _slot_ is a component of a stack frame, either a function parameter, +a [temporary](#lvalues-rvalues-and-temporaries), or a local variable. A _local variable_ (or *stack-local* allocation) holds a value directly, allocated within the stack's memory. The value is a part of the stack frame. -A _reference_ references a value outside the frame. It may refer to a -value allocated in another frame *or* a boxed value in the heap. The -reference-formation rules ensure that the referent will outlive the reference. - Local variables are immutable unless declared with `let mut`. The `mut` keyword applies to all local variables declared within that declaration (so `let mut x, y` declares two mutable variables, `x` and @@ -2891,20 +2887,6 @@ state. Subsequent statements within a function may or may not initialize the local variables. Local variables can be used only after they have been initialized; this is enforced by the compiler. -References are created for function arguments. If the compiler can not prove -that the referred-to value will outlive the reference, it will try to set -aside a copy of that value to refer to. If this is not semantically safe (for -example, if the referred-to value contains mutable fields), it will reject the -program. If the compiler deems copying the value expensive, it will warn. - -A function with an argument of type `&mut T`, for some type `T`, can write to -the slot that its argument refers to. An example of such a function is: - -~~~~~~~~ -fn incr(i: &mut int) { - *i = *i + 1; -} -~~~~~~~~ ### Memory boxes From 0b1a401bb73299640eaec28937228538d916887a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 19:15:40 -0700 Subject: [PATCH 162/292] manual: fix bullet list. --- doc/rust.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/rust.md b/doc/rust.md index 1f546c53ffbc..bc5b2e067e0f 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2979,6 +2979,7 @@ and data races on memory are prohibited by the type system. Inter-task communication and co-ordination facilities are provided in the standard library. These include: + - synchronous and asynchronous communication channels with various communication topologies - read-only and read-write shared variables with various safe mutual exclusion patterns - simple locks and semaphores From d81d4f1f3c94716c6dcafaf88d860aaa5d3598ca Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 19:22:53 -0700 Subject: [PATCH 163/292] manual: remove as many ~"" literals as possible. --- doc/rust.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index bc5b2e067e0f..d7cba1904791 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -859,8 +859,8 @@ fn main() { log(info, Some(1.0)); // Equivalent to 'log(core::info, - // core::str::to_upper(core::str::slice(~"foo", 0u, 1u)));' - log(info, to_upper(slice(~"foo", 0u, 1u))); + // core::str::to_upper(core::str::slice("foo", 0u, 1u)));' + log(info, to_upper(slice("foo", 0u, 1u))); } ~~~~ @@ -1050,14 +1050,14 @@ were declared without the `!` annotation, the following code would not typecheck: ~~~~ -# fn my_err(s: ~str) -> ! { fail } +# fn my_err(s: &str) -> ! { fail } fn f(i: int) -> int { if i == 42 { return 42; } else { - my_err(~"Bad number!"); + my_err("Bad number!"); } } ~~~~ @@ -1502,7 +1502,7 @@ string, boolean value, or the nil value. ~~~~~~~~ {.literals} (); // nil type -~"hello"; // string type +"hello"; // string type '5'; // character type 5; // integer type ~~~~~~~~ @@ -1520,7 +1520,7 @@ values. ~~~~~~~~ {.tuple} (0f, 4.5f); -(~"a", 4u, true); +("a", 4u, true); ~~~~~~~~ ### Record expressions @@ -1539,8 +1539,8 @@ written before its name. ~~~~ {x: 10f, y: 20f}; -{name: ~"Joe", age: 35u, score: 100_000}; -{ident: ~"X", mut count: 0u}; +{name: "Joe", age: 35u, score: 100_000}; +{ident: "X", mut count: 0u}; ~~~~ The order of the fields in a record expression is significant, and @@ -1609,7 +1609,7 @@ When no mutability is specified, the vector is immutable. ~~~~ ~[1, 2, 3, 4]; -~[~"a", ~"b", ~"c", ~"d"]; +~["a", "b", "c", "d"]; ~[mut 0u8, 0u8, 0u8, 0u8]; ~~~~ @@ -1633,7 +1633,7 @@ task in a _failing state_. (~[1, 2, 3, 4])[0]; (~[mut 'x', 'y'])[1] = 'z'; -(~[~"a", ~"b"])[10]; // fails +(~["a", "b"])[10]; // fails # } ~~~~ @@ -2034,7 +2034,7 @@ An example: let mut i = 0; while i < 10 { - io::println(~"hello\n"); + io::println("hello\n"); i = i + 1; } ~~~~ @@ -2281,9 +2281,9 @@ range of values may be specified with `..`. For example: # let x = 2; let message = match x { - 0 | 1 => ~"not many", - 2 .. 9 => ~"a few", - _ => ~"lots" + 0 | 1 => "not many", + 2 .. 9 => "a few", + _ => "lots" }; ~~~~ @@ -2366,7 +2366,7 @@ The following examples all produce the same output, logged at the `error` logging level: ~~~~ -# let filename = ~"bulbasaur"; +# let filename = "bulbasaur"; // Full version, logging a value. log(core::error, ~"file not found: " + filename); From 13ea16152d34368c44da05960135ba58ec622cda Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 19:25:09 -0700 Subject: [PATCH 164/292] manual: remove as many ~[] literals as possible. --- doc/rust.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index d7cba1904791..3254b3398a5f 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -908,10 +908,10 @@ declared, in an angle-bracket-enclosed, comma-separated list following the function name. ~~~~ {.xfail-test} -fn iter(seq: ~[T], f: fn(T)) { +fn iter(seq: &[T], f: fn(T)) { for seq.each |elt| { f(elt); } } -fn map(seq: ~[T], f: fn(T) -> U) -> ~[U] { +fn map(seq: &[T], f: fn(T) -> U) -> ~[U] { let mut acc = ~[]; for seq.each |elt| { acc.push(f(elt)); } acc @@ -1608,9 +1608,9 @@ indicate that the elements of the resulting vector may be mutated. When no mutability is specified, the vector is immutable. ~~~~ -~[1, 2, 3, 4]; -~["a", "b", "c", "d"]; -~[mut 0u8, 0u8, 0u8, 0u8]; +[1, 2, 3, 4]; +["a", "b", "c", "d"]; +[mut 0u8, 0u8, 0u8, 0u8]; ~~~~ ### Index expressions @@ -1631,9 +1631,9 @@ task in a _failing state_. ~~~~ # do task::spawn_unlinked { -(~[1, 2, 3, 4])[0]; -(~[mut 'x', 'y'])[1] = 'z'; -(~["a", "b"])[10]; // fails +([1, 2, 3, 4])[0]; +([mut 'x', 'y'])[1] = 'z'; +(["a", "b"])[10]; // fails # } ~~~~ @@ -1770,10 +1770,10 @@ Any other cast is unsupported and will fail to compile. An example of an `as` expression: ~~~~ -# fn sum(v: ~[float]) -> float { 0.0 } -# fn len(v: ~[float]) -> int { 0 } +# fn sum(v: &[float]) -> float { 0.0 } +# fn len(v: &[float]) -> int { 0 } -fn avg(v: ~[float]) -> float { +fn avg(v: &[float]) -> float { let sum: float = sum(v); let sz: float = len(v) as float; return sum / sz; @@ -1800,8 +1800,8 @@ No allocation or destruction is entailed. An example of three different move expressions: ~~~~~~~~ -# let mut x = ~[mut 0]; -# let a = ~[mut 0]; +# let mut x = &[mut 0]; +# let a = &[mut 0]; # let b = 0; # let y = {mut z: 0}; # let c = 0; @@ -1827,8 +1827,8 @@ No allocation or destruction is entailed. An example of three different swap expressions: ~~~~~~~~ -# let mut x = ~[mut 0]; -# let mut a = ~[mut 0]; +# let mut x = &[mut 0]; +# let mut a = &[mut 0]; # let i = 0; # let y = {mut z: 0}; # let b = {mut c: 0}; @@ -1929,11 +1929,11 @@ the unary copy operator is typically only used to cause an argument to a functio An example of a copy expression: ~~~~ -fn mutate(vec: ~[mut int]) { +fn mutate(vec: &[mut int]) { vec[0] = 10; } -let v = ~[mut 1,2,3]; +let v = &[mut 1,2,3]; mutate(copy v); // Pass a copy @@ -2716,7 +2716,7 @@ In this example, the trait `Printable` occurs as a type in both the type signatu Within the body of an item that has type parameter declarations, the names of its type parameters are types: ~~~~~~~ -fn map(f: fn(A) -> B, xs: ~[A]) -> ~[B] { +fn map(f: fn(A) -> B, xs: &[A]) -> ~[B] { if xs.len() == 0 { return ~[]; } let first: B = f(xs[0]); let rest: ~[B] = map(f, xs.slice(1, xs.len())); From 588d97d80ec7a36a3a83aa40c55df1a53c74d7e3 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 19:30:43 -0700 Subject: [PATCH 165/292] manual: fix accidentally broken test. --- doc/rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 3254b3398a5f..b64bb7eb5f93 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1929,11 +1929,11 @@ the unary copy operator is typically only used to cause an argument to a functio An example of a copy expression: ~~~~ -fn mutate(vec: &[mut int]) { +fn mutate(vec: ~[mut int]) { vec[0] = 10; } -let v = &[mut 1,2,3]; +let v = ~[mut 1,2,3]; mutate(copy v); // Pass a copy From 5bca5f7c5474083aeddca1d5c405ff08ec8322f4 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 11 Oct 2012 19:39:21 -0700 Subject: [PATCH 166/292] manual: fix one more nit. --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index b64bb7eb5f93..c26e2dfb906a 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1030,7 +1030,7 @@ A special kind of function can be declared with a `!` character where the output slot type would normally be. For example: ~~~~ -fn my_err(s: ~str) -> ! { +fn my_err(s: &str) -> ! { log(info, s); fail; } From 140d16ac5803a0e7b61d0f901a82549c09e4411f Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 19:44:48 -0700 Subject: [PATCH 167/292] Fix tutorial-ffi tests --- doc/tutorial-ffi.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md index 771384f41d83..895aaf224364 100644 --- a/doc/tutorial-ffi.md +++ b/doc/tutorial-ffi.md @@ -30,7 +30,7 @@ fn sha1(data: ~str) -> ~str unsafe { let bytes = str::to_bytes(data); let hash = crypto::SHA1(vec::raw::to_ptr(bytes), vec::len(bytes) as c_uint, ptr::null()); - return as_hex(vec::raw::from_buf(hash, 20)); + return as_hex(vec::from_buf(hash, 20)); } fn main(args: ~[~str]) { @@ -132,7 +132,7 @@ fn sha1(data: ~str) -> ~str { let bytes = str::to_bytes(data); let hash = crypto::SHA1(vec::raw::to_ptr(bytes), vec::len(bytes), ptr::null()); - return as_hex(vec::raw::from_buf(hash, 20)); + return as_hex(vec::from_buf(hash, 20)); } } ~~~~ @@ -177,7 +177,7 @@ Let's look at our `sha1` function again. let bytes = str::to_bytes(data); let hash = crypto::SHA1(vec::raw::to_ptr(bytes), vec::len(bytes), ptr::null()); -return as_hex(vec::raw::from_buf(hash, 20)); +return as_hex(vec::from_buf(hash, 20)); # } # } ~~~~ @@ -198,7 +198,7 @@ unsafe null pointer of type `*u8`. (Rust generics are awesome like that: they can take the right form depending on the type that they are expected to return.) -Finally, `vec::raw::from_buf` builds up a new `~[u8]` from the +Finally, `vec::from_buf` builds up a new `~[u8]` from the unsafe pointer that `SHA1` returned. SHA1 digests are always twenty bytes long, so we can pass `20` for the length of the new vector. From bb4dd06307ecb29621416076963d3853e17e55bc Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 20:03:24 -0700 Subject: [PATCH 168/292] manual: Lightly copyedit the macros section --- doc/rust.md | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index c26e2dfb906a..9956f9b05f35 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -501,14 +501,13 @@ only be invoked in expression position. any token other than a delimiter or `$`.) Macro invocations are looked up by name, and each macro rule is tried in turn; -the first successful match is transcribed. The matching and transcribing +the first successful match is transcribed. The matching and transcription processes are closely related, and will be described together: ### Macro By Example -Everything that does not begin with a `$` is matched and transcirbed -literally, including delimiters. For parsing reasons, they must be matched, -but they are otherwise not special. +The macro expander matches and transcribes every token that does not begin with a `$` literally, including delimiters. +For parsing reasons, delimiters must be balanced, but they are otherwise not special. In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust syntax named by _designator_. Valid designators are `item`, `block`, @@ -517,11 +516,11 @@ are the right-hand side and the left-hand side respectively of the `=>` in macro rules. In the transcriber, the designator is already known, and so only the name of a matched nonterminal comes after the dollar sign. -In bothe the matcher and transcriber, the Kleene star-like operator, -consisting of `$` and parens, optionally followed by a separator token, -followed by `*` or `+`, indicates repetition. (`*` means zero or more -repetitions, `+` means at least one repetition. The parens are not matched or -transcribed). On the matcher side, a name is bound to _all_ of the names it +In both the matcher and transcriber, the Kleene star-like operator indicates repetition. +The Kleene star operator consists of `$` and parens, optionally followed by a separator token, followed by `*` or `+`. +`*` means zero or more repetitions, `+` means at least one repetition. +The parens are not matched or transcribed. +On the matcher side, a name is bound to _all_ of the names it matches, in a structure that mimics the structure of the repetition encountered on a successful match. The job of the transcriber is to sort that structure out. @@ -550,19 +549,16 @@ 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. -2. The parser must have eliminated all ambiguity by the time it reaches a -`$` _name_ `:` _designator_. This most often affects them when they occur in -the beginning of, or immediately after, a `$(...)*`; requiring a distinctive -token in front can solve the problem. +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. ## Syntax extensions useful for the macro author * `log_syntax!` : print out the arguments at compile time -* `trace_macros!` : supply `true` or `false` to enable or disable printing -of the macro expansion process. -* `ident_to_str!` : turns the identifier argument into a string literal -* `concat_idents!` : creates a new identifier by concatenating its arguments +* `trace_macros!` : supply `true` or `false` to enable or disable printing of the macro expansion process. +* `ident_to_str!` : turn the identifier argument into a string literal +* `concat_idents!` : create a new identifier by concatenating the arguments From 91315c3c2f2b07cc090fa9d1a69aa389f3c605c2 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Oct 2012 20:09:41 -0700 Subject: [PATCH 169/292] manual: Lightly copyedit the crates section --- doc/rust.md | 66 +++++++++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 9956f9b05f35..bfdbf1155da1 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -388,11 +388,10 @@ Examples of floating-point literals of various forms: 12E+99_f64; // type f64 ~~~~ -##### Nil and boolean literals +##### Unit and boolean literals -The _nil value_, the only value of the type by the same name, is -written as `()`. The two values of the boolean type are written `true` -and `false`. +The _unit value_, the only value of the type that has the same name, is written as `()`. +The two values of the boolean type are written `true` and `false`. ### Symbols @@ -564,23 +563,19 @@ This requirement most often affects name-designator pairs when they occur at the # Crates and source files -Rust is a *compiled* language. Its semantics are divided along a -*phase distinction* between compile-time and run-time. Those semantic -rules that have a *static interpretation* govern the success or failure -of compilation. A program that fails to compile due to violation of a -compile-time rule has no defined semantics at run-time; the compiler should -halt with an error report, and produce no executable artifact. +Rust is a *compiled* language. +Its semantics obey a *phase distinction* between compile-time and run-time. +Those semantic rules that have a *static interpretation* govern the success or failure of compilation. +We refer to these rules as "static semantics". +Semantic rules called "dynamic semantics" govern the behavior of programs at run-time. +A program that fails to compile due to violation of a compile-time rule has no defined dynamic semantics; the compiler should halt with an error report, and produce no executable artifact. -The compilation model centres on artifacts called _crates_. Each compilation -is directed towards a single crate in source form, and if successful, -produces a single crate in binary form: either an executable or a library. +The compilation model centres on artifacts called _crates_. +Each compilation processes a single crate in source form, and if successful, produces a single crate in binary form: either an executable or a library. -A _crate_ is a unit of compilation and linking, as well as versioning, -distribution and runtime loading. A crate contains a _tree_ of nested -[module](#modules) scopes. The top level of this tree is a module that is -anonymous -- from the point of view of paths within the module -- and any item -within a crate has a canonical [module path](#paths) denoting its location -within the crate's module tree. +A _crate_ is a unit of compilation and linking, as well as versioning, distribution and runtime loading. +A crate contains a _tree_ of nested [module](#modules) scopes. +The top level of this tree is a module that is anonymous (from the point of view of paths within the module) and any item within a crate has a canonical [module path](#paths) denoting its location within the crate's module tree. Crates are provided to the Rust compiler through two kinds of file: @@ -590,18 +585,15 @@ Crates are provided to the Rust compiler through two kinds of file: > **Note:** The functionality of crate files will be merged into source files in future versions of Rust. > The separate processing of crate files, both their grammar and file extension, will be removed. -The Rust compiler is always invoked with a single input file, and always -produces a single output crate. +The Rust compiler is always invoked with a single crate file as input, and always produces a single output crate. When the Rust compiler is invoked with a crate file, it reads the _explicit_ definition of the crate it's compiling from that file, and populates the crate with modules derived from all the source files referenced by the crate, reading and processing all the referenced modules at once. -When the Rust compiler is invoked with a source file, it creates an -_implicit_ crate and treats the source file as though it was referenced as -the sole module populating this implicit crate. The module name is derived -from the source file name, with the `.rs` extension removed. +When the Rust compiler is invoked with a source file, it creates an _implicit_ crate and treats the source file as if it is the sole module populating this explicit crate. +The module name is derived from the source file name, with the `.rs` extension removed. ## Crate files @@ -658,10 +650,8 @@ containing source files and/or further subdirectories. The filesystem directory associated with a `dir_directive` module can either be explicit, or if omitted, is implicitly the same name as the module. -A `source_directive` references a source file, either explicitly or -implicitly by combining the module name with the file extension `.rs`. The -module contained in that source file is bound to the module path formed by -the `dir_directive` modules containing the `source_directive`. +A `source_directive` references a source file, either explicitly or implicitly, by combining the module name with the file extension `.rs`. +The module contained in that source file is bound to the module path formed by the `dir_directive` modules containing the `source_directive`. ## Source files @@ -671,9 +661,8 @@ location of which -- in the module tree of the current crate -- is defined from outside the source file: either by an explicit `source_directive` in a referencing crate file, or by the filename of the source file itself. -A source file that contains a `main` function can be compiled to an -executable. If a `main` function is present, -its return type must be [`nil`](#primitive-types) and it must take no arguments. +A source file that contains a `main` function can be compiled to an executable. +If a `main` function is present, its return type must be [`unit`](#primitive-types) and it must take no arguments. # Items and attributes @@ -1494,10 +1483,10 @@ A temporary's lifetime equals the largest lifetime of any borrowed pointer that A _literal expression_ consists of one of the [literal](#literals) forms described earlier. It directly describes a number, character, -string, boolean value, or the nil value. +string, boolean value, or the unit value. ~~~~~~~~ {.literals} -(); // nil type +(); // unit type "hello"; // string type '5'; // character type 5; // integer type @@ -1862,7 +1851,7 @@ operators may be composed with the `=` operator. The expression `lval OP= val` is equivalent to `lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`. -Any such expression always has the [`nil`](#primitive-types) type. +Any such expression always has the [`unit`](#primitive-types) type. #### Operator precedence @@ -2414,11 +2403,8 @@ types. User-defined types have limited capabilities. The primitive types are the following: -* The "nil" type `()`, having the single "nil" value `()`.^[The "nil" value - `()` is *not* a sentinel "null pointer" value for reference slots; the "nil" - type is the implicit return type from functions otherwise lacking a return - type, and can be used in other contexts (such as message-sending or - type-parametric code) as a zero-size type.] +* The "unit" type `()`, having the single "unit" value `()` (occasionally called "nil"). + ^[The "unit" value `()` is *not* a sentinel "null pointer" value for reference slots; the "unit" type is the implicit return type from functions otherwise lacking a return type, and can be used in other contexts (such as message-sending or type-parametric code) as a zero-size type.] * The boolean type `bool` with values `true` and `false`. * The machine types. * The machine-dependent integer and floating-point types. From c33bff955707d496d675126433627297487daa25 Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Thu, 11 Oct 2012 23:13:04 -0400 Subject: [PATCH 170/292] tutorial: add note about mutability of vectors --- doc/tutorial.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 04fd2aae3f7d..12850a92a038 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -216,7 +216,7 @@ while count < 10 { Although Rust can almost always infer the types of local variables, you can specify a variable's type by following it with a colon, then the type -name. +name. ~~~~ let monster_size: float = 57.8; @@ -381,6 +381,10 @@ of: `[mut T]` Mutable vector with unknown size ------------------------- ----------------------------------------------- +> ***Note***: In the future, mutability for vectors may be defined by +> the slot that contains the vector, not the type of the vector itself, +> deprecating [mut T] syntax. + In function types, the return type is specified with an arrow, as in the type `fn() -> bool` or the function declaration `fn foo() -> bool { }`. For functions that do not return a meaningful value, you can @@ -1951,7 +1955,7 @@ trait Printable { ~~~~ Traits may be implemented for specific types with [impls]. An impl -that implements a trait includes the name of the trait at the start of +that implements a trait includes the name of the trait at the start of the definition, as in the following impls of `Printable` for `int` and `~str`. From 45d1cd83ab903d377f3b03fd2dc74da42100e308 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 12 Oct 2012 12:02:08 -0700 Subject: [PATCH 171/292] Copyedit "Items and attributes" section in docs Most notably, I removed the "foldl" example in the section on pure functions, as IIRC this is no longer something you need an unsafe block for (pure functions are as pure as their arguments). Feel free to add an example where an unsafe block really is needed. --- doc/rust.md | 125 ++++++++++++++++++---------------------------------- 1 file changed, 44 insertions(+), 81 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index bfdbf1155da1..568f42976358 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -703,22 +703,19 @@ otherwise compose the item body. The meaning of these scoped items is the same as if the item was declared outside the scope -- it is still a static item -- except that the item's *path name* within the module namespace is qualified by the name of the enclosing item, or is private to the enclosing item (in the -case of functions). The exact locations in which sub-items may be declared is -given by the grammar. +case of functions). +The grammar specifies the exact locations in which sub-item declarations may appear. ### Type Parameters -All items except modules may be *parametrized* by type. Type parameters are +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 the type of the -item; in order to refer to the type-parametrized item, a referencing -[path](#paths) must in general provide type arguments as a list of -comma-separated types enclosed within angle brackets. 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. - +(`<...>`), 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. ### Modules @@ -763,9 +760,9 @@ mod math { view_item : extern_mod_decl | use_decl ; ~~~~~~~~ -A view item manages the namespace of a module; it does not define new items -but simply changes the visibility of other items. There are several kinds of -view item: +A view item manages the namespace of a module. +View items do not define new items, but rather, simply change other items' visibilit. +There are several kinds of view item: * [`extern mod` declarations](#extern-mod-declarations) * [`use` declarations](#use-declarations) @@ -789,7 +786,7 @@ compiler's library path and matching the `link_attrs` provided in the crate when it was compiled. If no `link_attrs` are provided, a default `name` attribute is assumed, equal to the `ident` given in the `use_decl`. -Two examples of `extern mod` declarations: +Three examples of `extern mod` declarations: ~~~~~~~~{.xfail-test} extern mod pcre (uuid = "54aba0f8-a7b1-4beb-92f1-4cf625264841"); @@ -844,8 +841,8 @@ fn main() { log(info, Some(1.0)); // Equivalent to 'log(core::info, - // core::str::to_upper(core::str::slice("foo", 0u, 1u)));' - log(info, to_upper(slice("foo", 0u, 1u))); + // core::str::to_upper(core::str::slice("foo", 0, 1)));' + log(info, to_upper(slice("foo", 0, 1))); } ~~~~ @@ -857,13 +854,9 @@ If a sequence of such redirections form a cycle or cannot be unambiguously resol ### Functions -A _function item_ defines a sequence of [statements](#statements) and an -optional final [expression](#expressions) associated with a name and a set of -parameters. Functions are declared with the keyword `fn`. Functions declare a -set of *input* [*slots*](#memory-slots) as parameters, through which the -caller passes arguments into the function, and an *output* -[*slot*](#memory-slots) through which the function passes results back to -the caller. +A _function item_ defines a sequence of [statements](#statements) and an optional final [expression](#expressions), along with a name and a set of parameters. +Functions are declared with the keyword `fn`. +Functions declare a set of *input* [*slots*](#memory-slots) as parameters, through which the caller passes arguments into the function, and an *output* [*slot*](#memory-slots) through which the function passes results back to the caller. A function may also be copied into a first class *value*, in which case the value has the corresponding [*function type*](#function-types), and can be @@ -941,12 +934,9 @@ Specifically, the following operations are considered unsafe: ##### Unsafe blocks -A block of code can also be prefixed with the `unsafe` keyword, -to permit a sequence of unsafe operations in an otherwise-safe function. -This facility exists because the static semantics of a Rust are a necessary approximation of the dynamic semantics. -When a programmer has sufficient conviction that a sequence of unsafe operations is actually safe, -they can encapsulate that sequence (taken as a whole) within an `unsafe` block. -The compiler will consider uses of such code "safe", to the surrounding context. +A block of code can also be prefixed with the `unsafe` keyword, to permit a sequence of unsafe operations in an otherwise-safe function. +This facility exists because the static semantics of Rust are a necessary approximation of the dynamic semantics. +When a programmer has sufficient conviction that a sequence of unsafe operations is actually safe, they can encapsulate that sequence (taken as a whole) within an `unsafe` block. The compiler will consider uses of such code "safe", to the surrounding context. #### Pure functions @@ -954,10 +944,9 @@ The compiler will consider uses of such code "safe", to the surrounding context. A pure function declaration is identical to a function declaration, except that it is declared with the additional keyword `pure`. In addition, the typechecker checks the body of a pure function with a restricted set of typechecking rules. -A pure function - -* may not contain an assignment or self-call expression; and -* may only call other pure functions, not general functions. +A pure function may only modify data owned by its own stack frame. +So, a pure function may modify a local variable allocated on the stack, but not a mutable reference that it takes as an argument. +A pure function may only call other pure functions, not general functions. An example of a pure function: @@ -978,36 +967,13 @@ pure fn nonempty_list(ls: List) -> bool { pure_length(ls) > 0u } These purity-checking rules approximate the concept of referential transparency: that a call-expression could be rewritten with the literal-expression of its return value, without changing the meaning of the program. Since they are an approximation, sometimes these rules are *too* restrictive. -Rust allows programmers to violate these rules using [`unsafe` blocks](#unsafe-blocks). +Rust allows programmers to violate these rules using [`unsafe` blocks](#unsafe-blocks), which we already saw. As with any `unsafe` block, those that violate static purity carry transfer the burden of safety-proof from the compiler to the programmer. Programmers should exercise caution when breaking such rules. -An example of a pure function that uses an unsafe block: - -~~~~ {.xfail-test} -# use std::list::*; - -fn pure_foldl(ls: List, u: U, f: fn(&T, &U) -> U) -> U { - match ls { - Nil => u, - Cons(hd, tl) => f(hd, pure_foldl(*tl, f(hd, u), f)) - } -} - -pure fn pure_length(ls: List) -> uint { - fn count(_t: &T, u: &uint) -> uint { *u + 1u } - unsafe { - pure_foldl(ls, 0u, count) - } -} -~~~~ - -Despite its name, `pure_foldl` is a `fn`, not a `pure fn`, because there is no -way in Rust to specify that the higher-order function argument `f` is a pure -function. So, to use `foldl` in a pure list length function that a pure function -could then use, we must use an `unsafe` block wrapped around the call to -`pure_foldl` in the definition of `pure_length`. +For more details on purity, see [the borrowed pointer tutorial][borrow]. +[borrow]: tutorial-borrowed-ptr.html #### Diverging functions @@ -1092,10 +1058,8 @@ specific type; the type-specified aspects of a value include: * The sequence of memory operations required to access the value. * The [kind](#type-kinds) of the type. -For example, the type `{x: u8, y: u8`} defines the set of immutable values -that are composite records, each containing two unsigned 8-bit integers -accessed through the components `x` and `y`, and laid out in memory with the -`x` component preceding the `y` component. +For example, the type `(u8, u8)` defines the set of immutable values that are composite pairs, +each containing two unsigned 8-bit integers accessed by pattern-matching and laid out in memory with the `x` component preceding the `y` component. ### Structures @@ -1111,7 +1075,7 @@ let px: int = p.x; ### Enumerations -An _enumeration_ is a simulatneous definition of a nominal [enumerated type](#enumerated-types) as well as a set of *constructors*, +An _enumeration_ is a simultaneous definition of a nominal [enumerated type](#enumerated-types) as well as a set of *constructors*, that can be used to create or pattern-match values of the corresponding enumerated type. Enumerations are declared with the keyword `enum`. @@ -1134,7 +1098,7 @@ a = Cat; const_item : "const" ident ':' type '=' expr ';' ; ~~~~~~~~ -A Constant is a named value stored in read-only memory in a crate. +A *constant* is a named value stored in read-only memory in a crate. The value bound to a constant is evaluated at compile time. Constants are declared with the `const` keyword. A constant item must have an expression giving its definition. @@ -1206,7 +1170,7 @@ let myshape: Shape = @mycircle as @Shape; ~~~~ The resulting value is a managed box containing the value that was cast, -along with information that identify the methods of the implementation that was used. +along with information that identifies the methods of the implementation that was used. Values with a trait type can have [methods called](#method-call-expressions) on them, for any method in the trait, and can be used to instantiate type parameters that are bounded by the trait. @@ -1271,9 +1235,9 @@ foreign_mod : [ foreign_fn ] * ; Foreign modules form the basis for Rust's foreign function interface. A foreign module describes functions in external, non-Rust -libraries. Functions within foreign modules are declared the same as other -Rust functions, with the exception that they may not have a body and are -instead terminated by a semi-colon. +libraries. +Functions within foreign modules are declared in the same way as other Rust functions, +with the exception that they may not have a body and are instead terminated by a semicolon. ~~~ # use libc::{c_char, FILE}; @@ -1284,9 +1248,8 @@ extern mod c { } ~~~ -Functions within foreign modules may be called by Rust code as it would any -normal function and the Rust compiler will automatically translate between -the Rust ABI and the foreign ABI. +Functions within foreign modules may be called by Rust code, just like functions defined in Rust. +The Rust compiler automatically translates between the Rust ABI and the foreign ABI. The name of the foreign module has special meaning to the Rust compiler in that it will treat the module name as the name of a library to link to, @@ -1300,7 +1263,7 @@ A number of [attributes](#attributes) control the behavior of foreign modules. By default foreign modules assume that the library they are calling use the -standard C "cdecl" ABI. Other ABI's may be specified using the `abi` +standard C "cdecl" ABI. Other ABIs may be specified using the `abi` attribute as in ~~~{.xfail-test} @@ -1310,15 +1273,15 @@ extern mod kernel32 { } ~~~ The `link_name` attribute allows the default library naming behavior to -be overriden by explicitly specifying the name of the library. +be overridden by explicitly specifying the name of the library. ~~~{.xfail-test} #[link_name = "crypto"] extern mod mycrypto { } ~~~ -The `nolink` attribute tells the Rust compiler not to perform any linking -for the foreign module. This is particularly useful for creating foreign +The `nolink` attribute tells the Rust compiler not to do any linking for the foreign module. +This is particularly useful for creating foreign modules for libc, which tends to not follow standard library naming conventions and is linked to all Rust programs anyway. @@ -1333,9 +1296,9 @@ attr : ident [ '=' literal Static entities in Rust -- crates, modules and items -- may have _attributes_ applied to them. ^[Attributes in Rust are modeled on Attributes in ECMA-335, -C#] An attribute is a general, free-form piece of metadata that is interpreted -according to name, convention, and language and compiler version. Attributes -may appear as any of: +C#] +An attribute is a general, free-form metadatum that is interpreted according to name, convention, and language and compiler version. +Attributes may appear as any of * A single identifier, the attribute name * An identifier followed by the equals sign '=' and a literal, providing a key/value pair From 1bede1f5e0012069feaf093a6287256af606ff92 Mon Sep 17 00:00:00 2001 From: Kevin Cantu Date: Fri, 12 Oct 2012 12:32:36 -0700 Subject: [PATCH 172/292] Replace several common macros of the form #m[...] with m!(...) This commit replaces nearly all remaining uses of #fmt, #debug, #error, and #info, and fixes some error messages... --- src/libstd/net_url.rs | 16 ++++++++-------- src/libstd/serialization.rs | 2 +- src/libstd/time.rs | 3 +-- src/libsyntax/diagnostic.rs | 2 +- src/libsyntax/ext/base.rs | 8 ++++---- src/libsyntax/ext/env.rs | 4 ++-- src/libsyntax/ext/fmt.rs | 16 ++++++++-------- src/libsyntax/parse/parser.rs | 6 +++--- src/rustc/driver/session.rs | 2 +- src/rustc/metadata/decoder.rs | 4 ++-- src/rustc/middle/borrowck/gather_loans.rs | 4 ++-- src/rustc/middle/borrowck/preserve.rs | 8 ++++---- src/rustc/middle/check_alt.rs | 2 +- src/rustc/middle/liveness.rs | 4 ++-- src/rustc/middle/resolve.rs | 4 ++-- src/rustc/middle/trans/glue.rs | 2 +- src/rustc/middle/trans/monomorphize.rs | 4 ++-- src/rustc/middle/ty.rs | 4 ++-- src/rustc/middle/typeck/collect.rs | 4 ++-- src/rustdoc/attr_pass.rs | 2 +- src/test/bench/task-perf-linked-failure.rs | 10 +++++----- .../borrowck-borrowed-uniq-rvalue-2.rs | 2 +- src/test/compile-fail/borrowck-unary-move-2.rs | 4 ++-- src/test/compile-fail/extenv-no-args.rs | 2 +- src/test/compile-fail/extenv-too-many-args.rs | 2 +- src/test/compile-fail/extfmt-no-args.rs | 2 +- src/test/compile-fail/extfmt-non-literal.rs | 2 +- src/test/compile-fail/extfmt-non-literal2.rs | 2 +- src/test/compile-fail/extfmt-unsigned-plus.rs | 2 +- src/test/compile-fail/extfmt-unsigned-space.rs | 2 +- src/test/compile-fail/issue-3099.rs | 6 +++--- src/test/compile-fail/regions-freevar.rs | 2 +- src/test/run-pass/early-vtbl-resolution.rs | 2 +- src/test/run-pass/issue-2904.rs | 2 +- src/test/run-pass/issue-2935.rs | 2 +- src/test/run-pass/issue-2989.rs | 4 ++-- src/test/run-pass/issue-3168.rs | 8 ++++---- src/test/run-pass/issue-3176.rs | 8 ++++---- src/test/run-pass/pure-fmt.rs | 4 ++-- src/test/run-pass/struct-literal-dtor.rs | 2 +- 40 files changed, 85 insertions(+), 86 deletions(-) diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index c3fd3383979b..109e71a3eaa7 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -65,10 +65,10 @@ fn encode_inner(s: &str, full_url: bool) -> ~str { str::push_char(&mut out, ch); } - _ => out += #fmt("%%%X", ch as uint) + _ => out += fmt!("%%%X", ch as uint) } } else { - out += #fmt("%%%X", ch as uint); + out += fmt!("%%%X", ch as uint); } } } @@ -164,7 +164,7 @@ fn encode_plus(s: &str) -> ~str { str::push_char(&mut out, ch); } ' ' => str::push_char(&mut out, '+'), - _ => out += #fmt("%%%X", ch as uint) + _ => out += fmt!("%%%X", ch as uint) } } @@ -190,7 +190,7 @@ pub fn encode_form_urlencoded(m: HashMap<~str, @DVec<@~str>>) -> ~str { first = false; } - out += #fmt("%s=%s", key, encode_plus(**value)); + out += fmt!("%s=%s", key, encode_plus(**value)); } } @@ -332,7 +332,7 @@ pub pure fn query_to_str(query: Query) -> ~str { let (k, v) = copy *kv; // This is really safe... unsafe { - strvec += ~[#fmt("%s=%s", + strvec += ~[fmt!("%s=%s", encode_component(k), encode_component(v))]; } }; @@ -850,7 +850,7 @@ mod tests { fn test_url_parse_host_slash() { let urlstr = ~"http://0.42.42.42/"; let url = from_str(urlstr).get(); - #debug("url: %?", url); + debug!("url: %?", url); assert url.host == ~"0.42.42.42"; assert url.path == ~"/"; } @@ -859,7 +859,7 @@ mod tests { fn test_url_with_underscores() { let urlstr = ~"http://dotcom.com/file_name.html"; let url = from_str(urlstr).get(); - #debug("url: %?", url); + debug!("url: %?", url); assert url.path == ~"/file_name.html"; } @@ -867,7 +867,7 @@ mod tests { fn test_url_with_dashes() { let urlstr = ~"http://dotcom.com/file-name.html"; let url = from_str(urlstr).get(); - #debug("url: %?", url); + debug!("url: %?", url); assert url.path == ~"/file-name.html"; } diff --git a/src/libstd/serialization.rs b/src/libstd/serialization.rs index 5173ef163a22..b7cf09cc6aa5 100644 --- a/src/libstd/serialization.rs +++ b/src/libstd/serialization.rs @@ -375,7 +375,7 @@ pub impl Option: Deserializable { match i { 0 => None, 1 => Some(d.read_enum_variant_arg(0u, || deserialize(d))), - _ => fail(#fmt("Bad variant for option: %u", i)) + _ => fail(fmt!("Bad variant for option: %u", i)) } } } diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 65872a013aba..75909273392f 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -595,8 +595,7 @@ pub fn strptime(s: &str, format: &str) -> Result { fn strftime(format: &str, tm: Tm) -> ~str { fn parse_type(ch: char, tm: &Tm) -> ~str { //FIXME (#2350): Implement missing types. - let die = || #fmt("strftime: can't understand this format %c ", - ch); + let die = || fmt!("strftime: can't understand this format %c ", ch); match ch { 'A' => match tm.tm_wday as int { 0 => ~"Sunday", diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 7f208a3a710c..2addb3d9e12a 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -266,7 +266,7 @@ fn print_macro_backtrace(cm: codemap::codemap, sp: span) { let ss = option::map_default(&ei.callie.span, @~"", |span| @codemap::span_to_str(*span, cm)); print_diagnostic(*ss, note, - fmt!("in expansion of #%s", ei.callie.name)); + fmt!("in expansion of %s!", ei.callie.name)); let ss = codemap::span_to_str(ei.call_site, cm); print_diagnostic(ss, note, ~"expansion site"); print_macro_backtrace(cm, ei.call_site); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index c106042b9a3d..94bf2a43f28a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -269,21 +269,21 @@ fn get_mac_args(cx: ext_ctxt, sp: span, arg: ast::mac_arg, match max { Some(max) if ! (min <= elts_len && elts_len <= max) => { cx.span_fatal(sp, - fmt!("#%s takes between %u and %u arguments.", + fmt!("%s! takes between %u and %u arguments.", name, min, max)); } None if ! (min <= elts_len) => { - cx.span_fatal(sp, fmt!("#%s needs at least %u arguments.", + cx.span_fatal(sp, fmt!("%s! needs at least %u arguments.", name, min)); } _ => return elts /* we are good */ } } _ => { - cx.span_fatal(sp, fmt!("#%s: malformed invocation", name)) + cx.span_fatal(sp, fmt!("%s!: malformed invocation", name)) } }, - None => cx.span_fatal(sp, fmt!("#%s: missing arguments", name)) + None => cx.span_fatal(sp, fmt!("%s!: missing arguments", name)) } } diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 8cecceb2e554..37fb0f05cbd3 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -1,6 +1,6 @@ /* - * The compiler code necessary to support the #env extension. Eventually this + * The compiler code necessary to support the env! extension. Eventually this * should all get sucked into either the compiler syntax extension plugin * interface. */ @@ -15,7 +15,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg, // FIXME (#2248): if this was more thorough it would manufacture an // Option rather than just an maybe-empty string. - let var = expr_to_str(cx, args[0], ~"#env requires a string"); + let var = expr_to_str(cx, args[0], ~"env! requires a string"); match os::getenv(var) { option::None => return mk_uniq_str(cx, sp, ~""), option::Some(s) => return mk_uniq_str(cx, sp, s) diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index ea493eab5617..e24575f6cd32 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -1,7 +1,7 @@ /* - * The compiler code necessary to support the #fmt extension. Eventually this + * The compiler code necessary to support the fmt! extension. Eventually this * should all get sucked into either the standard library extfmt module or the * compiler syntax extension plugin interface. */ @@ -16,7 +16,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: span, arg: ast::mac_arg, let args = get_mac_args_no_max(cx, sp, arg, 1u, ~"fmt"); let fmt = expr_to_str(cx, args[0], - ~"first argument to #fmt must be a string literal."); + ~"first argument to fmt! must be a string literal."); let fmtspan = args[0].span; debug!("Format string:"); log(debug, fmt); @@ -76,7 +76,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, let count_is_args = ~[count_lit]; return mk_call(cx, sp, count_is_path, count_is_args); } - _ => cx.span_unimpl(sp, ~"unimplemented #fmt conversion") + _ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion") } } fn make_ty(cx: ext_ctxt, sp: span, t: Ty) -> @ast::expr { @@ -133,7 +133,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, _ => return false } } - let unsupported = ~"conversion not supported in #fmt string"; + let unsupported = ~"conversion not supported in fmt! string"; match cnv.param { option::None => (), _ => cx.span_unimpl(sp, unsupported) @@ -145,14 +145,14 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, if !is_signed_type(cnv) { cx.span_fatal(sp, ~"+ flag only valid in " + - ~"signed #fmt conversion"); + ~"signed fmt! conversion"); } } FlagSpaceForSign => { if !is_signed_type(cnv) { cx.span_fatal(sp, ~"space flag only valid in " + - ~"signed #fmt conversions"); + ~"signed fmt! conversions"); } } FlagLeftZeroPad => (), @@ -252,7 +252,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, n += 1u; if n >= nargs { cx.span_fatal(sp, - ~"not enough arguments to #fmt " + + ~"not enough arguments to fmt! " + ~"for the given format string"); } debug!("Building conversion:"); @@ -267,7 +267,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, if expected_nargs < nargs { cx.span_fatal - (sp, fmt!("too many arguments to #fmt. found %u, expected %u", + (sp, fmt!("too many arguments to fmt!. found %u, expected %u", nargs, expected_nargs)); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c3c182d66873..4457c64a68c0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2414,7 +2414,7 @@ impl parser { fn expect_self_ident() { if !self.is_self_ident() { - self.fatal(#fmt("expected `self` but found `%s`", + self.fatal(fmt!("expected `self` but found `%s`", token_to_str(self.reader, self.token))); } self.bump(); @@ -2696,7 +2696,7 @@ impl parser { ctor_decl(a_fn_decl, attrs, blk, s) => { match the_ctor { Some((_, _, _, s_first)) => { - self.span_note(s, #fmt("Duplicate constructor \ + self.span_note(s, fmt!("Duplicate constructor \ declaration for class %s", *self.interner.get(class_name))); self.span_fatal(copy s_first, ~"First constructor \ @@ -2710,7 +2710,7 @@ impl parser { dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { - self.span_note(s, #fmt("Duplicate destructor \ + self.span_note(s, fmt!("Duplicate destructor \ declaration for class %s", *self.interner.get(class_name))); self.span_fatal(copy s_first, ~"First destructor \ diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs index e6d5c404371d..550656c23df6 100644 --- a/src/rustc/driver/session.rs +++ b/src/rustc/driver/session.rs @@ -216,7 +216,7 @@ impl session { // This exists to help with refactoring to eliminate impossible // cases later on fn impossible_case(sp: span, msg: &str) -> ! { - self.span_bug(sp, #fmt("Impossible case reached: %s", msg)); + self.span_bug(sp, fmt!("Impossible case reached: %s", msg)); } fn verbose() -> bool { self.debugging_opt(verbose) } fn time_passes() -> bool { self.debugging_opt(time_passes) } diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 689141b6bf34..4c647d41880e 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -162,7 +162,7 @@ fn item_family(item: ebml::Doc) -> Family { 'g' => PublicField, 'j' => PrivateField, 'N' => InheritedField, - c => fail (#fmt("unexpected family char: %c", c)) + c => fail (fmt!("unexpected family char: %c", c)) } } @@ -705,7 +705,7 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, self_ty: self_ty, vis: ast::public}); } - #debug("get_trait_methods: }"); + debug!("get_trait_methods: }"); @result } diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index f5ac40ce93d4..2030984ae704 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -303,8 +303,8 @@ impl gather_loan_ctxt { _ => { self.bccx.tcx.sess.span_bug( cmt.span, - #fmt["loans required but scope is scope_region is %s", - region_to_str(self.tcx(), scope_r)]); + fmt!("loans required but scope is scope_region is %s", + region_to_str(self.tcx(), scope_r))); } } } diff --git a/src/rustc/middle/borrowck/preserve.rs b/src/rustc/middle/borrowck/preserve.rs index 6bfb0d091a4c..7e1d47eed694 100644 --- a/src/rustc/middle/borrowck/preserve.rs +++ b/src/rustc/middle/borrowck/preserve.rs @@ -314,17 +314,17 @@ priv impl &preserve_ctxt { // we can only root values if the desired region is some concrete // scope within the fn body ty::re_scope(scope_id) => { - #debug["Considering root map entry for %s: \ + debug!("Considering root map entry for %s: \ node %d:%u -> scope_id %?, root_ub %?", self.bccx.cmt_to_repr(cmt), base.id, - derefs, scope_id, self.root_ub]; + derefs, scope_id, self.root_ub); if self.bccx.is_subregion_of(self.scope_region, root_region) { - #debug["Elected to root"]; + debug!("Elected to root"); let rk = {id: base.id, derefs: derefs}; self.bccx.root_map.insert(rk, scope_id); return Ok(pc_ok); } else { - #debug["Unable to root"]; + debug!("Unable to root"); return Err({cmt:cmt, code:err_out_of_root_scope(root_region, self.scope_region)}); diff --git a/src/rustc/middle/check_alt.rs b/src/rustc/middle/check_alt.rs index f71b82a2be7e..aab470f6907d 100644 --- a/src/rustc/middle/check_alt.rs +++ b/src/rustc/middle/check_alt.rs @@ -33,7 +33,7 @@ fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) { if arms.is_empty() { if !type_is_empty(tcx, pat_ty) { // We know the type is inhabited, so this must be wrong - tcx.sess.span_err(ex.span, #fmt("non-exhaustive patterns: \ + tcx.sess.span_err(ex.span, fmt!("non-exhaustive patterns: \ type %s is non-empty", ty_to_str(tcx, pat_ty))); } // If the type *is* empty, it's vacuously exhaustive diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 3ae0727de60d..9ef54eedcf5b 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -902,11 +902,11 @@ impl Liveness { self.propagate_through_fn_block(decl, body) }); - // hack to skip the loop unless #debug is enabled: + // hack to skip the loop unless debug! is enabled: debug!("^^ liveness computation results for body %d (entry=%s)", { for uint::range(0u, self.ir.num_live_nodes) |ln_idx| { - #debug["%s", self.ln_str(LiveNode(ln_idx))]; + debug!("%s", self.ln_str(LiveNode(ln_idx))); } body.node.id }, diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 5f30346a28e8..18880fe917b3 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -918,12 +918,12 @@ impl Resolver { match ns.find(|n| child.defined_in_namespace(n)) { Some(ns) => { self.session.span_err(sp, - #fmt("Duplicate definition of %s %s", + fmt!("Duplicate definition of %s %s", namespace_to_str(ns), self.session.str_of(name))); do child.span_for_namespace(ns).iter() |sp| { self.session.span_note(*sp, - #fmt("First definition of %s %s here:", + fmt!("First definition of %s %s here:", namespace_to_str(ns), self.session.str_of(name))); } diff --git a/src/rustc/middle/trans/glue.rs b/src/rustc/middle/trans/glue.rs index d60a5a0bd7df..af9f2899a54d 100644 --- a/src/rustc/middle/trans/glue.rs +++ b/src/rustc/middle/trans/glue.rs @@ -745,7 +745,7 @@ fn emit_tydescs(ccx: @crate_ctxt) { // Index tydesc by addrspace. if ti.addrspace > gc_box_addrspace { let llty = T_ptr(ccx.tydesc_type); - let addrspace_name = #fmt("_gc_addrspace_metadata_%u", + let addrspace_name = fmt!("_gc_addrspace_metadata_%u", ti.addrspace as uint); let addrspace_gvar = str::as_c_str(addrspace_name, |buf| { llvm::LLVMAddGlobal(ccx.llmod, llty, buf) diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 17eaf591c9f3..87c073d567d7 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -37,11 +37,11 @@ fn monomorphic_fn(ccx: @crate_ctxt, must_cast = true; } - #debug["monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?, \ + debug!("monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?, \ hash_id = %?", fn_id, ty::item_path_str(ccx.tcx, fn_id), real_substs.map(|s| ty_to_str(ccx.tcx, *s)), - substs.map(|s| ty_to_str(ccx.tcx, *s)), hash_id]; + substs.map(|s| ty_to_str(ccx.tcx, *s)), hash_id); match ccx.monomorphized.find(hash_id) { Some(val) => { diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index a0366cbc0b37..c1195d473aa5 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -3020,7 +3020,7 @@ fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field { match vec::find(get_fields(rec_ty), |f| f.ident == id) { Some(f) => f, // Do we only call this when we know the field is legit? - None => fail (#fmt("get_field: ty doesn't have a field %s", + None => fail (fmt!("get_field: ty doesn't have a field %s", tcx.sess.str_of(id))) } } @@ -3335,7 +3335,7 @@ fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@ast::method] { match ast_util::split_trait_methods(ms) { (_, p) => p }, - _ => cx.sess.bug(#fmt("provided_trait_methods: %? is not a trait", + _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait", id)) } } diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 18e29981af30..0a2643f6d0fe 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -266,7 +266,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, } if impl_m.tps.len() != trait_m.tps.len() { - tcx.sess.span_err(sp, #fmt("method `%s` \ + tcx.sess.span_err(sp, fmt!("method `%s` \ has %u type %s, but its trait declaration has %u type %s", tcx.sess.str_of(trait_m.ident), impl_m.tps.len(), pluralize(impl_m.tps.len(), ~"parameter"), @@ -291,7 +291,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, // Would be nice to use the ty param names in the error message, // but we don't have easy access to them here if impl_param_bounds.len() != trait_param_bounds.len() { - tcx.sess.span_err(sp, #fmt("in method `%s`, \ + tcx.sess.span_err(sp, fmt!("in method `%s`, \ type parameter %u has %u %s, but the same type \ parameter in its trait declaration has %u %s", tcx.sess.str_of(trait_m.ident), diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs index d5f0ca9f507b..56ebbfe9b51f 100644 --- a/src/rustdoc/attr_pass.rs +++ b/src/rustdoc/attr_pass.rs @@ -157,7 +157,7 @@ fn fold_enum( attr_parser::parse_desc(ast_variant.node.attrs) } - _ => fail #fmt("Enum variant %s has id that's not bound \ + _ => fail fmt!("Enum variant %s has id that's not bound \ to an enum item", variant.name) } }; diff --git a/src/test/bench/task-perf-linked-failure.rs b/src/test/bench/task-perf-linked-failure.rs index a692b2f3011e..bd2c3d1bc077 100644 --- a/src/test/bench/task-perf-linked-failure.rs +++ b/src/test/bench/task-perf-linked-failure.rs @@ -19,20 +19,20 @@ fn grandchild_group(num_tasks: uint) { comm::recv(comm::Port::<()>()); // block forever } } - #error["Grandchild group getting started"]; + error!("Grandchild group getting started"); for num_tasks.times { // Make sure all above children are fully spawned; i.e., enlisted in // their ancestor groups. comm::recv(po); } - #error["Grandchild group ready to go."]; + error!("Grandchild group ready to go."); // Master grandchild task exits early. } fn spawn_supervised_blocking(myname: &str, +f: fn~()) { let mut res = None; task::task().future_result(|+r| res = Some(r)).supervised().spawn(f); - #error["%s group waiting", myname]; + error!("%s group waiting", myname); let x = future::get(&option::unwrap(res)); assert x == task::Success; } @@ -58,10 +58,10 @@ fn main() { grandchild_group(num_tasks); } // When grandchild group is ready to go, make the middle group exit. - #error["Middle group wakes up and exits"]; + error!("Middle group wakes up and exits"); } // Grandparent group waits for middle group to be gone, then fails - #error["Grandparent group wakes up and fails"]; + error!("Grandparent group wakes up and fails"); fail; }; assert x.is_err(); diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs index f539045108ee..6cd22b7f5350 100644 --- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs +++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs @@ -1,6 +1,6 @@ struct defer { x: &[&str], - drop { #error["%?", self.x]; } + drop { error!("%?", self.x); } } fn defer(x: &r/[&r/str]) -> defer/&r { diff --git a/src/test/compile-fail/borrowck-unary-move-2.rs b/src/test/compile-fail/borrowck-unary-move-2.rs index 303415e46635..1d1595383ee7 100644 --- a/src/test/compile-fail/borrowck-unary-move-2.rs +++ b/src/test/compile-fail/borrowck-unary-move-2.rs @@ -1,5 +1,5 @@ struct noncopyable { - i: (), drop { #error["dropped"]; } + i: (), drop { error!("dropped"); } } fn noncopyable() -> noncopyable { @@ -13,4 +13,4 @@ enum wrapper = noncopyable; fn main() { let x1 = wrapper(noncopyable()); let _x2 = move *x1; //~ ERROR moving out of enum content -} \ No newline at end of file +} diff --git a/src/test/compile-fail/extenv-no-args.rs b/src/test/compile-fail/extenv-no-args.rs index e169db23bf26..1db0e0a39ee1 100644 --- a/src/test/compile-fail/extenv-no-args.rs +++ b/src/test/compile-fail/extenv-no-args.rs @@ -1,3 +1,3 @@ -// error-pattern:#env takes between 1 and 1 arguments +// error-pattern: env! takes between 1 and 1 arguments fn main() { env!(); } diff --git a/src/test/compile-fail/extenv-too-many-args.rs b/src/test/compile-fail/extenv-too-many-args.rs index ee5b1b4af74e..4f0df2a090fb 100644 --- a/src/test/compile-fail/extenv-too-many-args.rs +++ b/src/test/compile-fail/extenv-too-many-args.rs @@ -1,3 +1,3 @@ -// error-pattern:#env takes between 1 and 1 arguments +// error-pattern: env! takes between 1 and 1 arguments fn main() { env!("one", "two"); } diff --git a/src/test/compile-fail/extfmt-no-args.rs b/src/test/compile-fail/extfmt-no-args.rs index b291fbae2256..1cca7e5b315b 100644 --- a/src/test/compile-fail/extfmt-no-args.rs +++ b/src/test/compile-fail/extfmt-no-args.rs @@ -1,3 +1,3 @@ -// error-pattern:#fmt needs at least 1 arguments +// error-pattern:fmt! needs at least 1 arguments fn main() { fmt!(); } diff --git a/src/test/compile-fail/extfmt-non-literal.rs b/src/test/compile-fail/extfmt-non-literal.rs index 0e2109fac4f0..7255bd846318 100644 --- a/src/test/compile-fail/extfmt-non-literal.rs +++ b/src/test/compile-fail/extfmt-non-literal.rs @@ -1,7 +1,7 @@ // error-pattern: literal fn main() { - // #fmt's first argument must be a literal. Hopefully this + // fmt!'s first argument must be a literal. Hopefully this // restriction can be eased eventually to just require a // compile-time constant. let x = fmt!("a" + "b"); diff --git a/src/test/compile-fail/extfmt-non-literal2.rs b/src/test/compile-fail/extfmt-non-literal2.rs index cc10845fd9f1..0196c37c68ee 100644 --- a/src/test/compile-fail/extfmt-non-literal2.rs +++ b/src/test/compile-fail/extfmt-non-literal2.rs @@ -1,7 +1,7 @@ // error-pattern: literal fn main() { - // #fmt's first argument must be a literal. Hopefully this + // fmt!'s first argument must be a literal. Hopefully this // restriction can be eased eventually to just require a // compile-time constant. let x = fmt!(20); diff --git a/src/test/compile-fail/extfmt-unsigned-plus.rs b/src/test/compile-fail/extfmt-unsigned-plus.rs index d8a9f4fa98df..1dd3ed390d51 100644 --- a/src/test/compile-fail/extfmt-unsigned-plus.rs +++ b/src/test/compile-fail/extfmt-unsigned-plus.rs @@ -1,4 +1,4 @@ -// error-pattern:only valid in signed #fmt conversion +// error-pattern:only valid in signed fmt! conversion fn main() { // Can't use a sign on unsigned conversions diff --git a/src/test/compile-fail/extfmt-unsigned-space.rs b/src/test/compile-fail/extfmt-unsigned-space.rs index 001adb521cc3..a2ac54bea7d9 100644 --- a/src/test/compile-fail/extfmt-unsigned-space.rs +++ b/src/test/compile-fail/extfmt-unsigned-space.rs @@ -1,4 +1,4 @@ -// error-pattern:only valid in signed #fmt conversion +// error-pattern:only valid in signed fmt! conversion fn main() { // Can't use a space on unsigned conversions diff --git a/src/test/compile-fail/issue-3099.rs b/src/test/compile-fail/issue-3099.rs index 4f3bd89e7ef9..d5c016c1ea87 100644 --- a/src/test/compile-fail/issue-3099.rs +++ b/src/test/compile-fail/issue-3099.rs @@ -1,11 +1,11 @@ fn a(x: ~str) -> ~str { - #fmt("First function with %s", x) + fmt!("First function with %s", x) } fn a(x: ~str, y: ~str) -> ~str { //~ ERROR Duplicate definition of value a - #fmt("Second function with %s and %s", x, y) + fmt!("Second function with %s and %s", x, y) } fn main() { - #info("Result: "); + info!("Result: "); } diff --git a/src/test/compile-fail/regions-freevar.rs b/src/test/compile-fail/regions-freevar.rs index dc2a43cc7db9..b163006c50a6 100644 --- a/src/test/compile-fail/regions-freevar.rs +++ b/src/test/compile-fail/regions-freevar.rs @@ -3,7 +3,7 @@ fn wants_static_fn(_x: &static/fn()) {} fn main() { let i = 3; do wants_static_fn { - #debug("i=%d", i); + debug!("i=%d", i); //~^ ERROR captured variable does not outlive the enclosing closure } } diff --git a/src/test/run-pass/early-vtbl-resolution.rs b/src/test/run-pass/early-vtbl-resolution.rs index 2bbbbf7ef178..002d8b27ca7c 100644 --- a/src/test/run-pass/early-vtbl-resolution.rs +++ b/src/test/run-pass/early-vtbl-resolution.rs @@ -10,7 +10,7 @@ fn foo_func>(x: B) -> Option { x.foo() } fn main() { for iter::eachi(&(Some({a: 0}))) |i, a| { - #debug["%u %d", i, a.a]; + debug!("%u %d", i, a.a); } let _x: Option = foo_func(0); diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index 4bb2c561422c..b03cab1a828f 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -41,7 +41,7 @@ fn square_from_char(c: char) -> square { '.' => { earth } ' ' => { empty } _ => { - #error("invalid square: %?", c); + error!("invalid square: %?", c); fail } } diff --git a/src/test/run-pass/issue-2935.rs b/src/test/run-pass/issue-2935.rs index 855f5caf9a06..86ba11560b2a 100644 --- a/src/test/run-pass/issue-2935.rs +++ b/src/test/run-pass/issue-2935.rs @@ -19,6 +19,6 @@ fn main() { // x.f(); // y.f(); // (*z).f(); - #error["ok so far..."]; + error!("ok so far..."); z.f(); //segfault } diff --git a/src/test/run-pass/issue-2989.rs b/src/test/run-pass/issue-2989.rs index 0dd383e4039e..0cabe1adb28e 100644 --- a/src/test/run-pass/issue-2989.rs +++ b/src/test/run-pass/issue-2989.rs @@ -26,8 +26,8 @@ fn main() { let bools2 = to_bools({storage: ~[0b01100100]}); for uint::range(0, 8) |i| { - io::println(#fmt("%u => %u vs %u", i, bools[i] as uint, bools2[i] as uint)); + io::println(fmt!("%u => %u vs %u", i, bools[i] as uint, bools2[i] as uint)); } assert bools == bools2; -} \ No newline at end of file +} diff --git a/src/test/run-pass/issue-3168.rs b/src/test/run-pass/issue-3168.rs index 0da0ade08926..3154daffb23e 100644 --- a/src/test/run-pass/issue-3168.rs +++ b/src/test/run-pass/issue-3168.rs @@ -6,16 +6,16 @@ fn main() { let (c2,p2) = pipes::stream(); do task::spawn { p2.recv(); - #error["brother fails"]; + error!("brother fails"); fail; } let (c3,p3) = pipes::stream(); c.send(c3); c2.send(()); - #error["child blocks"]; + error!("child blocks"); p3.recv(); }; - #error["parent tries"]; + error!("parent tries"); assert !p.recv().try_send(()); - #error("all done!"); + error!("all done!"); } diff --git a/src/test/run-pass/issue-3176.rs b/src/test/run-pass/issue-3176.rs index 002c7d4c518a..7f89f4c49b70 100644 --- a/src/test/run-pass/issue-3176.rs +++ b/src/test/run-pass/issue-3176.rs @@ -8,18 +8,18 @@ fn main() { let (c2,p2) = pipes::stream(); do task::spawn { p2.recv(); - #error["brother fails"]; + error!("brother fails"); fail; } let (c3,p3) = pipes::stream(); c.send(c3); c2.send(()); - #error["child blocks"]; + error!("child blocks"); let (c, p) = pipes::stream(); (p, p3).select(); c.send(()); }; - #error["parent tries"]; + error!("parent tries"); assert !p.recv().try_send(()); - #error("all done!"); + error!("all done!"); } diff --git a/src/test/run-pass/pure-fmt.rs b/src/test/run-pass/pure-fmt.rs index 1671c3369fff..d757d0311b4e 100644 --- a/src/test/run-pass/pure-fmt.rs +++ b/src/test/run-pass/pure-fmt.rs @@ -1,4 +1,4 @@ -// Testing that calling #fmt (via #debug) doesn't complain about impure borrows +// Testing that calling fmt! (via debug!) doesn't complain about impure borrows pure fn foo() { let a = { @@ -18,4 +18,4 @@ pure fn foo() { } fn main() { -} \ No newline at end of file +} diff --git a/src/test/run-pass/struct-literal-dtor.rs b/src/test/run-pass/struct-literal-dtor.rs index e182fa67cf00..2b56cee9f6b4 100644 --- a/src/test/run-pass/struct-literal-dtor.rs +++ b/src/test/run-pass/struct-literal-dtor.rs @@ -1,6 +1,6 @@ struct foo { x: ~str, - drop { #error["%s", self.x]; } + drop { error!("%s", self.x); } } fn main() { From 57b4d10ff652d3beddae64782c882a07822bac3c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 12 Oct 2012 16:41:25 -0700 Subject: [PATCH 173/292] bump version to 0.5. --- Makefile.in | 2 +- src/cargo/cargo.rc | 10 +++++----- src/compiletest/compiletest.rc | 4 ++-- src/fuzzer/fuzzer.rc | 6 +++--- src/libcore/core.rc | 2 +- src/libcore/core.rs | 4 ++-- src/libstd/std.rc | 4 ++-- src/libsyntax/syntax.rc | 6 +++--- src/rustc/driver/rustc.rs | 8 ++++---- src/rustc/rustc.rc | 8 ++++---- src/rustdoc/rustdoc.rc | 10 +++++----- src/test/run-pass/use.rs | 2 +- 12 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Makefile.in b/Makefile.in index a7594261c295..383793be6f89 100644 --- a/Makefile.in +++ b/Makefile.in @@ -132,7 +132,7 @@ LIBSYNTAX_DSYM_GLOB :=$(call CFG_LIB_DSYM_GLOB,syntax) # version-string calculation CFG_GIT_DIR := $(CFG_SRC_DIR).git -CFG_RELEASE = 0.4 +CFG_RELEASE = 0.5 CFG_VERSION = $(CFG_RELEASE) ifneq ($(wildcard $(CFG_GIT)),) diff --git a/src/cargo/cargo.rc b/src/cargo/cargo.rc index 17ddacfd7eb7..76c15146310e 100644 --- a/src/cargo/cargo.rc +++ b/src/cargo/cargo.rc @@ -10,7 +10,7 @@ // End: #[link(name = "cargo", - vers = "0.4", + vers = "0.5", uuid = "9ff87a04-8fed-4295-9ff8-f99bb802650b", url = "https://github.com/mozilla/rust/tree/master/src/cargo")]; @@ -27,10 +27,10 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod rustc(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod rustc(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 991d2d2cb0e3..db605c3caa4c 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -8,8 +8,8 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); use core::*; diff --git a/src/fuzzer/fuzzer.rc b/src/fuzzer/fuzzer.rc index 640bcccc7a89..c4d37d904344 100644 --- a/src/fuzzer/fuzzer.rc +++ b/src/fuzzer/fuzzer.rc @@ -12,9 +12,9 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 94e6decc4ca8..484c58750328 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -25,7 +25,7 @@ Implicitly, all crates behave as if they included the following prologue: */ #[link(name = "core", - vers = "0.4", + vers = "0.5", uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", url = "https://github.com/mozilla/rust/tree/master/src/libcore")]; diff --git a/src/libcore/core.rs b/src/libcore/core.rs index 603f19362ee4..5ef11a4ad464 100644 --- a/src/libcore/core.rs +++ b/src/libcore/core.rs @@ -33,7 +33,7 @@ pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, BitAnd, BitOr, BitXor}; pub use ops::{Shl, Shr, Index}; #[cfg(test)] -extern mod coreops(name = "core", vers = "0.4"); +extern mod coreops(name = "core", vers = "0.5"); #[cfg(test)] pub use coreops::ops::{Const, Copy, Send, Owned}; @@ -72,6 +72,6 @@ mod core { // Similar to above. Some magic to make core testable. #[cfg(test)] mod std { - extern mod std(vers = "0.4"); + extern mod std(vers = "0.5"); pub use std::test; } diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 88ef03aa5349..bbffde409484 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -8,7 +8,7 @@ not required in or otherwise suitable for the core library. */ #[link(name = "std", - vers = "0.4", + vers = "0.5", uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; @@ -25,7 +25,7 @@ not required in or otherwise suitable for the core library. #[allow(deprecated_mode)]; #[forbid(deprecated_pattern)]; -extern mod core(vers = "0.4"); +extern mod core(vers = "0.5"); use core::*; // General io and system-services modules diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 93ed5bd471bc..7c73deed1a91 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -1,5 +1,5 @@ #[link(name = "syntax", - vers = "0.4", + vers = "0.5", uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")]; @@ -16,8 +16,8 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); use core::*; diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index e6a9d726f6d4..5833723ec101 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -3,10 +3,10 @@ #[allow(non_camel_case_types)]; #[legacy_modes]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod rustc(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod rustc(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc index dad27b706e60..5d1b217e6238 100644 --- a/src/rustc/rustc.rc +++ b/src/rustc/rustc.rc @@ -1,7 +1,7 @@ // -*- rust -*- #[link(name = "rustc", - vers = "0.4", + vers = "0.5", uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf", url = "https://github.com/mozilla/rust/tree/master/src/rustc")]; @@ -19,9 +19,9 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; diff --git a/src/rustdoc/rustdoc.rc b/src/rustdoc/rustdoc.rc index f8714b0e9bac..e8f0ec005452 100644 --- a/src/rustdoc/rustdoc.rc +++ b/src/rustdoc/rustdoc.rc @@ -1,7 +1,7 @@ //! Rustdoc - The Rust documentation generator #[link(name = "rustdoc", - vers = "0.4", + vers = "0.5", uuid = "f8abd014-b281-484d-a0c3-26e3de8e2412", url = "https://github.com/mozilla/rust/tree/master/src/rustdoc")]; @@ -18,10 +18,10 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.4"); -extern mod std(vers = "0.4"); -extern mod rustc(vers = "0.4"); -extern mod syntax(vers = "0.4"); +extern mod core(vers = "0.5"); +extern mod std(vers = "0.5"); +extern mod rustc(vers = "0.5"); +extern mod syntax(vers = "0.5"); use core::*; use std::par; diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index 10c9fcae8e74..850adcf6746f 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -1,7 +1,7 @@ #[no_core]; extern mod core; extern mod zed(name = "core"); -extern mod bar(name = "core", vers = "0.4"); +extern mod bar(name = "core", vers = "0.5"); use core::str; From cb55e246ba517a14eaabb82cba3294ab4ad23c0a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 12 Oct 2012 17:00:08 -0700 Subject: [PATCH 174/292] Use the Nth impl when translating a static method call, instead of the 0th. 0th is only correct when there are no bound tps on the trait. Fixes #3741. --- src/libsyntax/ast.rs | 9 ++- src/libsyntax/ast_util.rs | 2 +- src/rustc/metadata/decoder.rs | 64 +++++++++++-------- src/rustc/metadata/encoder.rs | 1 + src/rustc/middle/astencode.rs | 4 +- src/rustc/middle/resolve.rs | 1 + src/rustc/middle/trans/callee.rs | 5 +- src/rustc/middle/trans/expr.rs | 7 +- src/rustc/middle/trans/meth.rs | 43 ++++++++++++- src/rustc/middle/typeck/check.rs | 4 +- ...tic-method-in-trait-with-tps-intracrate.rs | 25 ++++++++ 11 files changed, 122 insertions(+), 43 deletions(-) create mode 100644 src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 435f52b4bf82..4b9454942935 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -118,7 +118,9 @@ type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; #[auto_deserialize] enum def { def_fn(def_id, purity), - def_static_method(def_id, purity), + def_static_method(/* method */ def_id, + /* trait */ def_id, + purity), def_self(node_id), def_mod(def_id), def_foreign_mod(def_id), @@ -150,9 +152,10 @@ impl def : cmp::Eq { _ => false } } - def_static_method(e0a, e1a) => { + def_static_method(e0a, e1a, e2a) => { match (*other) { - def_static_method(e0b, e1b) => e0a == e0b && e1a == e1b, + def_static_method(e0b, e1b, e2b) => + e0a == e0b && e1a == e1b && e2a == e2b, _ => false } } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 31ddcfafa2d6..35b9e8d40c01 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -54,7 +54,7 @@ fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} { pure fn def_id_of_def(d: def) -> def_id { match d { - def_fn(id, _) | def_static_method(id, _) | def_mod(id) | + def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | def_use(id) | def_class(id, _) => { diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 4c647d41880e..38838120a103 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -178,6 +178,12 @@ fn item_parent_item(d: ebml::Doc) -> Option { None } +fn item_reqd_and_translated_parent_item(cnum: ast::crate_num, + d: ebml::Doc) -> ast::def_id { + let trait_did = item_parent_item(d).expect(~"item without parent"); + {crate: cnum, node: trait_did.node} +} + fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id { let tagdoc = ebml::get_doc(d, tag_def_id); return translate_def_id(cdata, ebml::with_doc_data(tagdoc, @@ -297,35 +303,39 @@ fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident { } fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) - -> def_like { + -> def_like +{ let fam = item_family(item); match fam { - Const => dl_def(ast::def_const(did)), - Class => dl_def(ast::def_class(did, true)), - Struct => dl_def(ast::def_class(did, false)), - UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), - Fn => dl_def(ast::def_fn(did, ast::impure_fn)), - PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), - ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), - UnsafeStaticMethod => dl_def(ast::def_static_method(did, - ast::unsafe_fn)), - StaticMethod => dl_def(ast::def_static_method(did, ast::impure_fn)), - PureStaticMethod => dl_def(ast::def_static_method(did, ast::pure_fn)), - Type | ForeignType => dl_def(ast::def_ty(did)), - Mod => dl_def(ast::def_mod(did)), - ForeignMod => dl_def(ast::def_foreign_mod(did)), - Variant => { - match item_parent_item(item) { - Some(t) => { - let tid = {crate: cnum, node: t.node}; - dl_def(ast::def_variant(tid, did)) - } - None => fail ~"item_to_def_like: enum item has no parent" - } - } - Trait | Enum => dl_def(ast::def_ty(did)), - Impl => dl_impl(did), - PublicField | PrivateField | InheritedField => dl_field, + Const => dl_def(ast::def_const(did)), + Class => dl_def(ast::def_class(did, true)), + Struct => dl_def(ast::def_class(did, false)), + UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), + Fn => dl_def(ast::def_fn(did, ast::impure_fn)), + PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), + ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), + UnsafeStaticMethod => { + let trait_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_static_method(did, trait_did, ast::unsafe_fn)) + } + StaticMethod => { + let trait_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_static_method(did, trait_did, ast::impure_fn)) + } + PureStaticMethod => { + let trait_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_static_method(did, trait_did, ast::pure_fn)) + } + Type | ForeignType => dl_def(ast::def_ty(did)), + Mod => dl_def(ast::def_mod(did)), + ForeignMod => dl_def(ast::def_foreign_mod(did)), + Variant => { + let enum_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_variant(enum_did, did)) + } + Trait | Enum => dl_def(ast::def_ty(did)), + Impl => dl_impl(did), + PublicField | PrivateField | InheritedField => dl_field, } } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index f188d8ee5d8c..63a7ce1ac74c 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -794,6 +794,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(ty_m.id)); + encode_parent_item(ebml_w, local_def(item.id)); encode_name(ecx, ebml_w, ty_m.ident); encode_family(ebml_w, purity_static_method_family(ty_m.purity)); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 103f1eecf87a..15b20c41b674 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -345,8 +345,8 @@ impl ast::def: tr { fn tr(xcx: extended_decode_ctxt) -> ast::def { match self { ast::def_fn(did, p) => { ast::def_fn(did.tr(xcx), p) } - ast::def_static_method(did, p) => { - ast::def_static_method(did.tr(xcx), p) + ast::def_static_method(did, did2, p) => { + ast::def_static_method(did.tr(xcx), did2.tr(xcx), p) } ast::def_self(nid) => { ast::def_self(xcx.tr_id(nid)) } ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 18880fe917b3..314dea1b5763 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -1126,6 +1126,7 @@ impl Resolver { self.add_child(ident, new_parent, ~[ValueNS], ty_m.span); let def = def_static_method(local_def(ty_m.id), + local_def(item.id), ty_m.purity); (*method_name_bindings).define_value (Public, def, ty_m.span); diff --git a/src/rustc/middle/trans/callee.rs b/src/rustc/middle/trans/callee.rs index c851c5bc7250..aa998fb7b92d 100644 --- a/src/rustc/middle/trans/callee.rs +++ b/src/rustc/middle/trans/callee.rs @@ -78,8 +78,9 @@ fn trans(bcx: block, expr: @ast::expr) -> Callee { ast::def_fn(did, _) => { fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id)) } - ast::def_static_method(did, _) => { - fn_callee(bcx, meth::trans_static_method_callee(bcx, did, + ast::def_static_method(impl_did, trait_did, _) => { + fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did, + trait_did, ref_expr.id)) } ast::def_variant(tid, vid) => { diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 4e50f7a848e0..c841d9bd9137 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -641,10 +641,11 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr, let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id); return fn_data_to_datum(bcx, did, fn_data, lldest); } - ast::def_static_method(did, _) => { - let fn_data = meth::trans_static_method_callee(bcx, did, + ast::def_static_method(impl_did, trait_did, _) => { + let fn_data = meth::trans_static_method_callee(bcx, impl_did, + trait_did, ref_expr.id); - return fn_data_to_datum(bcx, did, fn_data, lldest); + return fn_data_to_datum(bcx, impl_did, fn_data, lldest); } ast::def_variant(tid, vid) => { if ty::enum_variant_with_id(ccx.tcx, tid, vid).args.len() > 0u { diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs index d8a2fda4d14b..96cf7fabd1f7 100644 --- a/src/rustc/middle/trans/meth.rs +++ b/src/rustc/middle/trans/meth.rs @@ -162,11 +162,50 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id, fn trans_static_method_callee(bcx: block, method_id: ast::def_id, + trait_id: ast::def_id, callee_id: ast::node_id) -> FnData { let _icx = bcx.insn_ctxt("impl::trans_static_method_callee"); let ccx = bcx.ccx(); + debug!("trans_static_method_callee(method_id=%?, trait_id=%s, \ + callee_id=%?)", + method_id, + ty::item_path_str(bcx.tcx(), trait_id), + callee_id); + let _indenter = indenter(); + + // When we translate a static fn defined in a trait like: + // + // trait Trait { + // static fn foo(...) {...} + // } + // + // this winds up being translated as something like: + // + // fn foo,M1...Mn>(...) {...} + // + // So when we see a call to this function foo, we have to figure + // out which impl the `Trait` bound on the type `self` was + // bound to. Due to the fact that we use a flattened list of + // impls, one per bound, this means we have to total up the bounds + // found on the type parametesr T1...Tn to find the index of the + // one we are interested in. + let bound_index = { + let trait_polyty = ty::lookup_item_type(bcx.tcx(), trait_id); + let mut index = 0; + for trait_polyty.bounds.each |param_bounds| { + for param_bounds.each |param_bound| { + match *param_bound { + ty::bound_trait(_) => { index += 1; } + ty::bound_copy | ty::bound_owned | + ty::bound_send | ty::bound_const => {} + } + } + } + index + }; + let mname = if method_id.crate == ast::local_crate { match bcx.tcx().items.get(method_id.node) { ast_map::node_trait_method(trait_method, _, _) => { @@ -187,9 +226,7 @@ fn trans_static_method_callee(bcx: block, let vtbls = resolve_vtables_in_fn_ctxt( bcx.fcx, ccx.maps.vtable_map.get(callee_id)); - // FIXME(#3446) -- I am pretty sure index 0 is not the right one, - // if the static method is implemented on a generic type. (NDM) - match vtbls[0] { + match vtbls[bound_index] { typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => { let mth_id = method_with_name(bcx.ccx(), impl_did, mname); diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index c1ab29758f2d..bf0ca36dddf4 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2403,13 +2403,13 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> } ast::def_fn(id, ast::unsafe_fn) | - ast::def_static_method(id, ast::unsafe_fn) => { + ast::def_static_method(id, _, ast::unsafe_fn) => { // Unsafe functions can only be touched in an unsafe context fcx.require_unsafe(sp, ~"access to unsafe function"); return ty::lookup_item_type(fcx.ccx.tcx, id); } - ast::def_fn(id, _) | ast::def_static_method(id, _) | + ast::def_fn(id, _) | ast::def_static_method(id, _, _) | ast::def_const(id) | ast::def_variant(_, id) | ast::def_class(id, _) => { return ty::lookup_item_type(fcx.ccx.tcx, id); diff --git a/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs b/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs new file mode 100644 index 000000000000..ac00f6a645b3 --- /dev/null +++ b/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs @@ -0,0 +1,25 @@ +trait Deserializer { + fn read_int() -> int; +} + +trait Deserializable { + static fn deserialize(d: &D) -> self; +} + +impl int: Deserializable { + static fn deserialize(d: &D) -> int { + return d.read_int(); + } +} + +struct FromThinAir { dummy: () } + +impl FromThinAir: Deserializer { + fn read_int() -> int { 22 } +} + +fn main() { + let d = FromThinAir { dummy: () }; + let i: int = deserialize(&d); + assert i == 22; +} \ No newline at end of file From 98887cc7eec0550d8364e98483ee26595b692ef8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Oct 2012 11:49:01 -0700 Subject: [PATCH 175/292] remove ctor from ast (take 2) (no review: just dead code removal) --- src/libsyntax/ast.rs | 9 +- src/libsyntax/ast_map.rs | 20 +- src/libsyntax/ast_util.rs | 13 +- src/libsyntax/fold.rs | 19 -- src/libsyntax/parse/parser.rs | 65 +---- src/libsyntax/print/pprust.rs | 12 - src/libsyntax/visit.rs | 33 +-- src/rustc/metadata/decoder.rs | 6 +- src/rustc/metadata/encoder.rs | 22 +- src/rustc/middle/astencode.rs | 23 +- src/rustc/middle/borrowck/check_loans.rs | 60 ++--- src/rustc/middle/borrowck/gather_loans.rs | 10 +- src/rustc/middle/kind.rs | 6 +- src/rustc/middle/liveness.rs | 234 ++++-------------- src/rustc/middle/region.rs | 20 +- src/rustc/middle/resolve.rs | 79 ++---- src/rustc/middle/trans/base.rs | 79 +----- src/rustc/middle/trans/common.rs | 5 - src/rustc/middle/trans/debuginfo.rs | 4 - src/rustc/middle/trans/inline.rs | 4 - src/rustc/middle/trans/monomorphize.rs | 13 +- src/rustc/middle/trans/reachable.rs | 11 - src/rustc/middle/trans/type_use.rs | 3 - src/rustc/middle/ty.rs | 5 +- src/rustc/middle/typeck/astconv.rs | 2 +- src/rustc/middle/typeck/check.rs | 16 +- src/rustc/middle/typeck/check/alt.rs | 2 +- src/rustc/middle/typeck/collect.rs | 24 -- .../compile-fail/cap-clause-use-after-move.rs | 6 +- src/test/compile-fail/issue-2590.rs | 2 +- .../compile-fail/regions-glb-free-free.rs | 2 +- 31 files changed, 137 insertions(+), 672 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 4b9454942935..3740557b7f8f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -137,7 +137,7 @@ enum def { @def, // closed over def node_id, // expr node that creates the closure node_id), // id for the block/body of the closure expr - def_class(def_id, bool /* has constructor */), + def_class(def_id), def_typaram_binder(node_id), /* class, impl or trait that has ty params */ def_region(node_id), def_label(node_id) @@ -238,9 +238,9 @@ impl def : cmp::Eq { _ => false } } - def_class(e0a, e1a) => { + def_class(e0a) => { match (*other) { - def_class(e0b, e1b) => e0a == e0b && e1a == e1b, + def_class(e0b) => e0a == e0b, _ => false } } @@ -1465,8 +1465,6 @@ type struct_def = { fields: ~[@struct_field], /* fields */ methods: ~[@method], /* methods */ /* (not including ctor or dtor) */ - /* ctor is optional, and will soon go away */ - ctor: Option, /* dtor is optional */ dtor: Option }; @@ -1566,7 +1564,6 @@ enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), ii_foreign(@foreign_item), - ii_ctor(class_ctor, ident, ~[ty_param], def_id /* parent id */), ii_dtor(class_dtor, ident, ~[ty_param], def_id /* parent id */) } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index d05c6eadaf6a..8555ceed2dbd 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -71,9 +71,6 @@ enum ast_node { // order they are introduced. node_arg(arg, uint), node_local(uint), - // Constructor for a class - // def_id is parent id - node_ctor(ident, ~[ty_param], @class_ctor, def_id, @path), // Destructor for a class node_dtor(~[ty_param], @class_dtor, def_id, @path), node_block(blk), @@ -132,7 +129,7 @@ fn map_decoded_item(diag: span_handler, // don't decode and instantiate the impl, but just the method, we have to // add it to the table now: match ii { - ii_item(*) | ii_ctor(*) | ii_dtor(*) => { /* fallthrough */ } + ii_item(*) | ii_dtor(*) => { /* fallthrough */ } ii_foreign(i) => { cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic, @path)); @@ -155,18 +152,6 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, cx.local_id += 1u; } match fk { - visit::fk_ctor(nm, attrs, tps, self_id, parent_id) => { - let ct = @{node: {id: id, - attrs: attrs, - self_id: self_id, - dec: /* FIXME (#2543) */ copy decl, - body: /* FIXME (#2543) */ copy body}, - span: sp}; - cx.map.insert(id, node_ctor(/* FIXME (#2543) */ copy nm, - /* FIXME (#2543) */ copy tps, - ct, parent_id, - @/* FIXME (#2543) */ copy cx.path)); - } visit::fk_dtor(tps, attrs, self_id, parent_id) => { let dt = @{node: {id: id, attrs: attrs, self_id: self_id, body: /* FIXME (#2543) */ copy body}, span: sp}; @@ -382,9 +367,6 @@ fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { Some(node_local(_)) => { // add more info here fmt!("local (id=%?)", id) } - Some(node_ctor(*)) => { // add more info here - fmt!("node_ctor (id=%?)", id) - } Some(node_dtor(*)) => { // add more info here fmt!("node_dtor (id=%?)", id) } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 35b9e8d40c01..4c18b6b8ecac 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -57,7 +57,7 @@ pure fn def_id_of_def(d: def) -> def_id { def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | - def_use(id) | def_class(id, _) => { + def_use(id) | def_class(id) => { id } def_arg(id, _) | def_local(id, _) | def_self(id) | @@ -338,7 +338,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => /* FIXME (#2543) */ copy i.ident, ii_foreign(i) => /* FIXME (#2543) */ copy i.ident, ii_method(_, m) => /* FIXME (#2543) */ copy m.ident, - ii_ctor(_, nm, _, _) => /* FIXME (#2543) */ copy nm, ii_dtor(_, nm, _, _) => /* FIXME (#2543) */ copy nm } } @@ -348,7 +347,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => i.id, ii_foreign(i) => i.id, ii_method(_, m) => m.id, - ii_ctor(ctor, _, _, _) => ctor.node.id, ii_dtor(dtor, _, _, _) => dtor.node.id } } @@ -358,9 +356,6 @@ impl inlined_item: inlined_item_utils { ii_item(i) => v.visit_item(i, e, v), ii_foreign(i) => v.visit_foreign_item(i, e, v), ii_method(_, m) => visit::visit_method_helper(m, e, v), - ii_ctor(ctor, nm, tps, parent_id) => { - visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v); - } ii_dtor(dtor, _, tps, parent_id) => { visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v); } @@ -494,12 +489,6 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { vfn(id); match fk { - visit::fk_ctor(_, _, tps, self_id, parent_id) => { - for vec::each(tps) |tp| { vfn(tp.id); } - vfn(id); - vfn(self_id); - vfn(parent_id.node); - } visit::fk_dtor(tps, _, self_id, parent_id) => { for vec::each(tps) |tp| { vfn(tp.id); } vfn(id); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 088df01985ee..68d9cd80430d 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -271,23 +271,6 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold) -> @ast::struct_def { - let resulting_optional_constructor; - match struct_def.ctor { - None => { - resulting_optional_constructor = None; - } - Some(constructor) => { - resulting_optional_constructor = Some({ - node: { - body: fld.fold_block(constructor.node.body), - dec: fold_fn_decl(constructor.node.dec, fld), - id: fld.new_id(constructor.node.id), - .. constructor.node - }, - .. constructor - }); - } - } let dtor = do option::map(&struct_def.dtor) |dtor| { let dtor_body = fld.fold_block(dtor.node.body); let dtor_id = fld.new_id(dtor.node.id); @@ -298,7 +281,6 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold) traits: vec::map(struct_def.traits, |p| fold_trait_ref(*p, fld)), fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)), methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)), - ctor: resulting_optional_constructor, dtor: dtor }; } @@ -585,7 +567,6 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ { |f| fld.fold_struct_field(*f)), methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)), - ctor: None, dtor: dtor }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4457c64a68c0..973822ddff9b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -115,8 +115,7 @@ enum class_member { So that we can distinguish a class ctor or dtor from other class members */ -enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span), - dtor_decl(blk, ~[attribute], codemap::span), +enum class_contents { dtor_decl(blk, ~[attribute], codemap::span), members(~[@class_member]) } type arg_or_capture_item = Either; @@ -2683,30 +2682,13 @@ impl parser { let mut fields: ~[@struct_field]; let mut methods: ~[@method] = ~[]; - let mut the_ctor: Option<(fn_decl, ~[attribute], blk, codemap::span)> - = None; let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None; - let ctor_id = self.get_id(); if self.eat(token::LBRACE) { // It's a record-like struct. fields = ~[]; while self.token != token::RBRACE { match self.parse_class_item() { - ctor_decl(a_fn_decl, attrs, blk, s) => { - match the_ctor { - Some((_, _, _, s_first)) => { - self.span_note(s, fmt!("Duplicate constructor \ - declaration for class %s", - *self.interner.get(class_name))); - self.span_fatal(copy s_first, ~"First constructor \ - declared here"); - } - None => { - the_ctor = Some((a_fn_decl, attrs, blk, s)); - } - } - } dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { @@ -2764,36 +2746,14 @@ impl parser { self_id: self.get_id(), body: d_body}, span: d_s}}; - match the_ctor { - Some((ct_d, ct_attrs, ct_b, ct_s)) => { - (class_name, - item_class(@{ - traits: traits, - fields: move fields, - methods: move methods, - ctor: Some({ - node: {id: ctor_id, - attrs: ct_attrs, - self_id: self.get_id(), - dec: ct_d, - body: ct_b}, - span: ct_s}), - dtor: actual_dtor - }, ty_params), - None) - } - None => { - (class_name, - item_class(@{ - traits: traits, - fields: move fields, - methods: move methods, - ctor: None, - dtor: actual_dtor - }, ty_params), - None) - } - } + (class_name, + item_class(@{ + traits: traits, + fields: move fields, + methods: move methods, + dtor: actual_dtor + }, ty_params), + None) } fn token_is_pound_or_doc_comment(++tok: token::token) -> bool { @@ -3097,12 +3057,6 @@ impl parser { let mut methods: ~[@method] = ~[]; while self.token != token::RBRACE { match self.parse_class_item() { - ctor_decl(*) => { - self.span_fatal(copy self.span, - ~"deprecated explicit \ - constructors are not allowed \ - here"); - } dtor_decl(blk, attrs, s) => { match the_dtor { Some((_, _, s_first)) => { @@ -3143,7 +3097,6 @@ impl parser { traits: ~[], fields: move fields, methods: move methods, - ctor: None, dtor: actual_dtor }; } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index bff356e5cb72..b98014f421bb 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -653,18 +653,6 @@ fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param], } bopen(s); hardbreak_if_not_bol(s); - do struct_def.ctor.iter |ctor| { - maybe_print_comment(s, ctor.span.lo); - print_outer_attributes(s, ctor.node.attrs); - // Doesn't call head because there shouldn't be a space after new. - cbox(s, indent_unit); - ibox(s, 4); - word(s.s, ~"new("); - print_fn_args(s, ctor.node.dec, ~[], None); - word(s.s, ~")"); - space(s.s); - print_block(s, ctor.node.body); - } do struct_def.dtor.iter |dtor| { hardbreak_if_not_bol(s); maybe_print_comment(s, dtor.span.lo); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index e6fd65eb458a..50fbd21f7b8d 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -17,8 +17,6 @@ enum fn_kind { fk_method(ident, ~[ty_param], @method), fk_anon(proto, capture_clause), //< an anonymous function like fn@(...) fk_fn_block(capture_clause), //< a block {||...} - fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */, - def_id /* parent class id */), // class constructor fk_dtor(~[ty_param], ~[attribute], node_id /* self id */, def_id /* parent class id */) // class destructor @@ -26,8 +24,9 @@ enum fn_kind { fn name_of_fn(fk: fn_kind) -> ident { match fk { - fk_item_fn(name, _, _) | fk_method(name, _, _) - | fk_ctor(name, _, _, _, _) => /* FIXME (#2543) */ copy name, + fk_item_fn(name, _, _) | fk_method(name, _, _) => { + /* FIXME (#2543) */ copy name + } fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon, fk_dtor(*) => parse::token::special_idents::dtor } @@ -35,11 +34,11 @@ fn name_of_fn(fk: fn_kind) -> ident { fn tps_of_fn(fk: fn_kind) -> ~[ty_param] { match fk { - fk_item_fn(_, tps, _) | fk_method(_, tps, _) - | fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) => { - /* FIXME (#2543) */ copy tps - } - fk_anon(*) | fk_fn_block(*) => ~[] + fk_item_fn(_, tps, _) | fk_method(_, tps, _) | + fk_dtor(tps, _, _, _) => { + /* FIXME (#2543) */ copy tps + } + fk_anon(*) | fk_fn_block(*) => ~[] } } @@ -291,17 +290,6 @@ fn visit_method_helper(m: @method, e: E, v: vt) { m.decl, m.body, m.span, m.id, e, v); } -// Similar logic to the comment on visit_method_helper - Tim -fn visit_class_ctor_helper(ctor: class_ctor, nm: ident, tps: ~[ty_param], - parent_id: def_id, e: E, v: vt) { - v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm, - ctor.node.attrs, - /* FIXME (#2543) */ copy tps, - ctor.node.self_id, parent_id), - ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v) - -} - fn visit_class_dtor_helper(dtor: class_dtor, tps: ~[ty_param], parent_id: def_id, e: E, v: vt) { v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs, @@ -330,7 +318,7 @@ fn visit_trait_method(m: trait_method, e: E, v: vt) { } } -fn visit_struct_def(sd: @struct_def, nm: ast::ident, tps: ~[ty_param], +fn visit_struct_def(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param], id: node_id, e: E, v: vt) { for sd.fields.each |f| { v.visit_struct_field(*f, e, v); @@ -341,9 +329,6 @@ fn visit_struct_def(sd: @struct_def, nm: ast::ident, tps: ~[ty_param], for sd.traits.each |p| { visit_path(p.path, e, v); } - do option::iter(&sd.ctor) |ctor| { - visit_class_ctor_helper(*ctor, nm, tps, ast_util::local_def(id), e, v); - }; do option::iter(&sd.dtor) |dtor| { visit_class_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v) }; diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 38838120a103..e639449a8573 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -124,7 +124,6 @@ enum Family { Variant, // v Impl, // i Trait, // I - Class, // C Struct, // S PublicField, // g PrivateField, // j @@ -157,7 +156,6 @@ fn item_family(item: ebml::Doc) -> Family { 'v' => Variant, 'i' => Impl, 'I' => Trait, - 'C' => Class, 'S' => Struct, 'g' => PublicField, 'j' => PrivateField, @@ -308,8 +306,7 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) let fam = item_family(item); match fam { Const => dl_def(ast::def_const(did)), - Class => dl_def(ast::def_class(did, true)), - Struct => dl_def(ast::def_class(did, false)), + Struct => dl_def(ast::def_class(did)), UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), Fn => dl_def(ast::def_fn(did, ast::impure_fn)), PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), @@ -832,7 +829,6 @@ fn item_family_to_str(fam: Family) -> ~str { Variant => ~"variant", Impl => ~"impl", Trait => ~"trait", - Class => ~"class", Struct => ~"struct", PublicField => ~"public field", PrivateField => ~"private field", diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 63a7ce1ac74c..2fdd39a2ca48 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -635,12 +635,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, /* Now, make an item for the class itself */ ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); - - match struct_def.ctor { - None => encode_family(ebml_w, 'S'), - Some(_) => encode_family(ebml_w, 'C') - } - + encode_family(ebml_w, 'S'); encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); @@ -699,21 +694,6 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, let bkts = create_index(idx); encode_index(ebml_w, bkts, write_int); ebml_w.end_tag(); - - /* Encode the constructor */ - for struct_def.ctor.each |ctor| { - debug!("encoding info for ctor %s %d", - ecx.tcx.sess.str_of(item.ident), ctor.node.id); - index.push({ - val: ctor.node.id, - pos: ebml_w.writer.tell() - }); - encode_info_for_ctor(ecx, ebml_w, ctor.node.id, item.ident, - path, if tps.len() > 0u { - Some(ii_ctor(*ctor, item.ident, tps, - local_def(item.id))) } - else { None }, tps); - } } item_impl(tps, opt_trait, _, methods) => { add_to_index(); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 15b20c41b674..d1f766dd8672 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -261,13 +261,6 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } - ast::ii_ctor(ctor, nm, tps, parent_id) => { - let ctor_body = fld.fold_block(ctor.node.body); - let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); - ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl, - .. ctor.node}, - .. ctor}, nm, tps, parent_id) - } ast::ii_dtor(dtor, nm, tps, parent_id) => { let dtor_body = fld.fold_block(dtor.node.body); ast::ii_dtor({node: {body: dtor_body, @@ -301,18 +294,6 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } - ast::ii_ctor(ctor, nm, tps, parent_id) => { - let ctor_body = fld.fold_block(ctor.node.body); - let ctor_attrs = fld.fold_attributes(ctor.node.attrs); - let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld); - let new_params = fold::fold_ty_params(tps, fld); - let ctor_id = fld.new_id(ctor.node.id); - let new_parent = xcx.tr_def_id(parent_id); - ast::ii_ctor({node: {body: ctor_body, attrs: ctor_attrs, - dec: ctor_decl, id: ctor_id, - .. ctor.node}, - .. ctor}, nm, new_params, new_parent) - } ast::ii_dtor(dtor, nm, tps, parent_id) => { let dtor_body = fld.fold_block(dtor.node.body); let dtor_attrs = fld.fold_attributes(dtor.node.attrs); @@ -368,8 +349,8 @@ impl ast::def: tr { xcx.tr_id(nid2), xcx.tr_id(nid3)) } - ast::def_class(did, has_constructor) => { - ast::def_class(did.tr(xcx), has_constructor) + ast::def_class(did) => { + ast::def_class(did.tr(xcx)) } ast::def_region(nid) => ast::def_region(xcx.tr_id(nid)), ast::def_typaram_binder(nid) => { diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index cc8d89a8ace7..6a9195b45096 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -17,10 +17,6 @@ enum check_loan_ctxt = @{ reported: HashMap, - // Keep track of whether we're inside a ctor, so as to - // allow mutating immutable fields in the same class if - // we are in a ctor, we track the self id - mut in_ctor: bool, mut declared_purity: ast::purity, mut fn_args: @~[ast::node_id] }; @@ -62,7 +58,6 @@ fn check_loans(bccx: borrowck_ctxt, let clcx = check_loan_ctxt(@{bccx: bccx, req_maps: req_maps, reported: HashMap(), - mut in_ctor: false, mut declared_purity: ast::impure_fn, mut fn_args: @~[]}); let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr, @@ -320,10 +315,7 @@ impl check_loan_ctxt { debug!("check_assignment(cmt=%s)", self.bccx.cmt_to_repr(cmt)); - if self.in_ctor && self.is_self_field(cmt) - && at.checked_by_liveness() { - // assigning to self.foo in a ctor is always allowed. - } else if self.is_local_variable(cmt) && at.checked_by_liveness() { + if self.is_local_variable(cmt) && at.checked_by_liveness() { // liveness guarantees that immutable local variables // are only assigned once } else { @@ -542,42 +534,28 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visitor: visit::vt) { debug!("purity on entry=%?", copy self.declared_purity); - do save_and_restore(&mut(self.in_ctor)) { - do save_and_restore(&mut(self.declared_purity)) { - do save_and_restore(&mut(self.fn_args)) { - let is_stack_closure = self.is_stack_closure(id); - let fty = ty::node_id_to_type(self.tcx(), id); - self.declared_purity = ty::determine_inherited_purity( - copy self.declared_purity, - ty::ty_fn_purity(fty), - ty::ty_fn_proto(fty)); + do save_and_restore(&mut(self.declared_purity)) { + do save_and_restore(&mut(self.fn_args)) { + let is_stack_closure = self.is_stack_closure(id); + let fty = ty::node_id_to_type(self.tcx(), id); + self.declared_purity = ty::determine_inherited_purity( + copy self.declared_purity, + ty::ty_fn_purity(fty), + ty::ty_fn_proto(fty)); - // In principle, we could consider fk_anon(*) or - // fk_fn_block(*) to be in a ctor, I suppose, but the - // purpose of the in_ctor flag is to allow modifications - // of otherwise immutable fields and typestate wouldn't be - // able to "see" into those functions anyway, so it - // wouldn't be very helpful. - match fk { - visit::fk_ctor(*) => { - self.in_ctor = true; - self.fn_args = @decl.inputs.map(|i| i.id ); - } - visit::fk_anon(*) | - visit::fk_fn_block(*) if is_stack_closure => { - self.in_ctor = false; + match fk { + visit::fk_anon(*) | + visit::fk_fn_block(*) if is_stack_closure => { // inherits the fn_args from enclosing ctxt - } - visit::fk_anon(*) | visit::fk_fn_block(*) | - visit::fk_method(*) | visit::fk_item_fn(*) | - visit::fk_dtor(*) => { - self.in_ctor = false; - self.fn_args = @decl.inputs.map(|i| i.id ); - } } - - visit::visit_fn(fk, decl, body, sp, id, self, visitor); + visit::fk_anon(*) | visit::fk_fn_block(*) | + visit::fk_method(*) | visit::fk_item_fn(*) | + visit::fk_dtor(*) => { + self.fn_args = @decl.inputs.map(|i| i.id ); + } } + + visit::visit_fn(fk, decl, body, sp, id, self, visitor); } } debug!("purity on exit=%?", copy self.declared_purity); diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index 2030984ae704..a2c8f1850713 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -71,11 +71,11 @@ fn req_loans_in_fn(fk: visit::fn_kind, self.root_ub = body.node.id; match fk { - visit::fk_anon(*) | visit::fk_fn_block(*) => {} - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => { - self.item_ub = body.node.id; - } + visit::fk_anon(*) | visit::fk_fn_block(*) => {} + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => { + self.item_ub = body.node.id; + } } visit::visit_fn(fk, decl, body, sp, id, self, v); diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index e2b85441a8fd..7b473cedb4c5 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -181,9 +181,9 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, // variables. This list is used below to avoid checking and reporting // on a given variable twice. let cap_clause = match fk { - visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc, - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => @~[] + visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc, + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => @~[] }; let captured_vars = do (*cap_clause).map |cap_item| { let cap_def = cx.tcx.def_map.get(cap_item.id); diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 9ef54eedcf5b..5ead871a661f 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -35,12 +35,6 @@ * Any use of the variable where the variable is dead afterwards is a * last use. * - * # Extension to handle constructors - * - * Each field is assigned an index just as with local variables. A use of - * `self` is considered a use of all fields. A use of `self.f` is just a use - * of `f`. - * * # Implementation details * * The actual implementation contains two (nested) walks over the AST. @@ -96,8 +90,6 @@ * - `no_ret_var`: a synthetic variable that is only 'read' from, the * fallthrough node. This allows us to detect functions where we fail * to return explicitly. - * - * - `self_var`: a variable representing 'self' */ use dvec::DVec; @@ -230,9 +222,11 @@ impl LiveNode { fn invalid_node() -> LiveNode { LiveNode(uint::max_value) } -enum RelevantDef { RelevantVar(node_id), RelevantSelf } - -type CaptureInfo = {ln: LiveNode, is_move: bool, rv: RelevantDef}; +struct CaptureInfo { + ln: LiveNode, + is_move: bool, + var_nid: node_id +} enum LocalKind { FromMatch(binding_mode), @@ -250,18 +244,15 @@ struct LocalInfo { enum VarKind { Arg(node_id, ident, rmode), Local(LocalInfo), - Field(ident), Self, ImplicitRet } -fn relevant_def(def: def) -> Option { +fn relevant_def(def: def) -> Option { match def { - def_self(_) => Some(RelevantSelf), - def_binding(nid, _) | def_arg(nid, _) | - def_local(nid, _) => Some(RelevantVar(nid)), + def_local(nid, _) => Some(nid), _ => None } @@ -276,7 +267,6 @@ struct IrMaps { mut num_vars: uint, live_node_map: HashMap, variable_map: HashMap, - field_map: HashMap, capture_map: HashMap, mut var_kinds: ~[VarKind], mut lnks: ~[LiveNodeKind], @@ -293,7 +283,6 @@ fn IrMaps(tcx: ty::ctxt, method_map: typeck::method_map, live_node_map: HashMap(), variable_map: HashMap(), capture_map: HashMap(), - field_map: HashMap(), var_kinds: ~[], lnks: ~[] } @@ -323,15 +312,12 @@ impl IrMaps { self.num_vars += 1u; match vk { - Local(LocalInfo {id:node_id, _}) | - Arg(node_id, _, _) => { - self.variable_map.insert(node_id, v); - } - Field(name) => { - self.field_map.insert(name, v); - } - Self | ImplicitRet => { - } + Local(LocalInfo {id:node_id, _}) | + Arg(node_id, _, _) => { + self.variable_map.insert(node_id, v); + } + Self | ImplicitRet => { + } } debug!("%s is %?", v.to_str(), vk); @@ -351,11 +337,10 @@ impl IrMaps { fn variable_name(var: Variable) -> ~str { match copy self.var_kinds[*var] { - Local(LocalInfo {ident: nm, _}) | - Arg(_, nm, _) => self.tcx.sess.str_of(nm), - Field(nm) => ~"self." + self.tcx.sess.str_of(nm), - Self => ~"self", - ImplicitRet => ~"" + Local(LocalInfo {ident: nm, _}) | + Arg(_, nm, _) => self.tcx.sess.str_of(nm), + Self => ~"self", + ImplicitRet => ~"" } } @@ -399,7 +384,7 @@ impl IrMaps { (*v).push(id); } Arg(_, _, by_ref) | - Arg(_, _, by_val) | Self | Field(_) | ImplicitRet | + Arg(_, _, by_val) | Self | ImplicitRet | Local(LocalInfo {kind: FromMatch(bind_by_implicit_ref), _}) => { debug!("--but it is not owned"); } @@ -428,13 +413,6 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, // and so forth: visit::visit_fn(fk, decl, body, sp, id, fn_maps, v); - match fk { - visit::fk_ctor(_, _, _, _, class_did) => { - add_class_fields(fn_maps, class_did); - } - _ => {} - } - // Special nodes and variables: // - exit_ln represents the end of the fn, either by return or fail // - implicit_ret_var is a pseudo-variable that represents @@ -442,8 +420,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, let specials = { exit_ln: (*fn_maps).add_live_node(ExitNode), fallthrough_ln: (*fn_maps).add_live_node(ExitNode), - no_ret_var: (*fn_maps).add_variable(ImplicitRet), - self_var: (*fn_maps).add_variable(Self) + no_ret_var: (*fn_maps).add_variable(ImplicitRet) }; // compute liveness @@ -460,18 +437,9 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, }); check_vt.visit_block(body, lsets, check_vt); lsets.check_ret(id, sp, fk, entry_ln); - lsets.check_fields(sp, entry_ln); lsets.warn_about_unused_args(sp, decl, entry_ln); } -fn add_class_fields(self: @IrMaps, did: def_id) { - for ty::lookup_class_fields(self.tcx, did).each |field_ty| { - assert field_ty.id.crate == local_crate; - let var = self.add_variable(Field(field_ty.ident)); - self.field_map.insert(field_ty.ident, var); - } -} - fn visit_local(local: @local, &&self: @IrMaps, vt: vt<@IrMaps>) { let def_map = self.tcx.def_map; do pat_util::pat_bindings(def_map, local.node.pat) |_bm, p_id, sp, path| { @@ -540,7 +508,9 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) { cap_move | cap_drop => true, // var must be dead afterwards cap_copy | cap_ref => false // var can still be used }; - call_caps.push({ln: cv_ln, is_move: is_move, rv: rv}); + call_caps.push(CaptureInfo {ln: cv_ln, + is_move: is_move, + var_nid: rv}); } None => {} } @@ -595,8 +565,7 @@ fn invalid_users() -> users { type Specials = { exit_ln: LiveNode, fallthrough_ln: LiveNode, - no_ret_var: Variable, - self_var: Variable + no_ret_var: Variable }; const ACC_READ: uint = 1u; @@ -647,19 +616,12 @@ impl Liveness { } } - fn variable_from_rdef(rv: RelevantDef, span: span) -> Variable { - match rv { - RelevantSelf => self.s.self_var, - RelevantVar(nid) => self.variable(nid, span) - } - } - fn variable_from_path(expr: @expr) -> Option { match expr.node { expr_path(_) => { let def = self.tcx.def_map.get(expr.id); relevant_def(def).map( - |rdef| self.variable_from_rdef(*rdef, expr.span) + |rdef| self.variable(*rdef, expr.span) ) } _ => None @@ -675,7 +637,7 @@ impl Liveness { match self.tcx.def_map.find(node_id) { Some(def) => { relevant_def(def).map( - |rdef| self.variable_from_rdef(*rdef, span) + |rdef| self.variable(*rdef, span) ) } None => { @@ -934,14 +896,6 @@ impl Liveness { } } - // as above, the "self" variable is a non-owned variable - self.acc(self.s.exit_ln, self.s.self_var, ACC_READ); - - // in a ctor, there is an implicit use of self.f for all fields f: - for self.ir.field_map.each_value |var| { - self.acc(self.s.exit_ln, var, ACC_READ|ACC_USE); - } - // the fallthrough exit is only for those cases where we do not // explicitly return: self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln); @@ -1023,24 +977,11 @@ impl Liveness { // Interesting cases with control flow or which gen/kill expr_path(_) => { - self.access_path(expr, succ, ACC_READ | ACC_USE) + self.access_path(expr, succ, ACC_READ | ACC_USE) } - expr_field(e, nm, _) => { - // If this is a reference to `self.f` inside of a ctor, - // then we treat it as a read of that variable. - // Otherwise, we ignore it and just propagate down to - // process `e`. - match self.as_self_field(e, nm) { - Some((ln, var)) => { - self.init_from_succ(ln, succ); - self.acc(ln, var, ACC_READ | ACC_USE); - ln - } - None => { - self.propagate_through_expr(e, succ) - } - } + expr_field(e, _, _) => { + self.propagate_through_expr(e, succ) } expr_fn(*) | expr_fn_block(*) => { @@ -1049,7 +990,7 @@ impl Liveness { let caps = (*self.ir).captures(expr); do (*caps).foldr(succ) |cap, succ| { self.init_from_succ(cap.ln, succ); - let var = self.variable_from_rdef(cap.rv, expr.span); + let var = self.variable(cap.var_nid, expr.span); self.acc(cap.ln, var, ACC_READ | ACC_USE); cap.ln } @@ -1269,8 +1210,8 @@ impl Liveness { // In general, the full flow graph structure for an // assignment/move/etc can be handled in one of two ways, // depending on whether what is being assigned is a "tracked - // value" or not. A tracked value is basically a local variable - // or argument, or a self-field (`self.f`) in a ctor. + // value" or not. A tracked value is basically a local + // variable or argument. // // The two kinds of graphs are: // @@ -1293,12 +1234,11 @@ impl Liveness { // // # Tracked lvalues // - // A tracked lvalue is either a local variable/argument `x` or - // else it is a self-field `self.f` in a constructor. In + // A tracked lvalue is a local variable/argument `x`. In // these cases, the link_node where the write occurs is linked - // to node id of `x` or `self`, respectively. The - // `write_lvalue()` routine generates the contents of this - // node. There are no subcomponents to consider. + // to node id of `x`. The `write_lvalue()` routine generates + // the contents of this node. There are no subcomponents to + // consider. // // # Non-tracked lvalues // @@ -1315,12 +1255,9 @@ impl Liveness { // just ignore such cases and treat them as reads. match expr.node { - expr_path(_) => succ, - expr_field(e, nm, _) => match self.as_self_field(e, nm) { - Some(_) => succ, - None => self.propagate_through_expr(e, succ) - }, - _ => self.propagate_through_expr(expr, succ) + expr_path(_) => succ, + expr_field(e, _, _) => self.propagate_through_expr(e, succ), + _ => self.propagate_through_expr(expr, succ) } } @@ -1330,14 +1267,6 @@ impl Liveness { acc: uint) -> LiveNode { match expr.node { expr_path(_) => self.access_path(expr, succ, acc), - expr_field(e, nm, _) => match self.as_self_field(e, nm) { - Some((ln, var)) => { - self.init_from_succ(ln, succ); - self.acc(ln, var, acc); - ln - } - None => succ - }, // We do not track other lvalues, so just propagate through // to their subcomponents. Also, it may happen that @@ -1350,27 +1279,7 @@ impl Liveness { fn access_path(expr: @expr, succ: LiveNode, acc: uint) -> LiveNode { let def = self.tcx.def_map.get(expr.id); match relevant_def(def) { - Some(RelevantSelf) => { - // Accessing `self` is like accessing every field of - // the current object. This allows something like - // `self = ...;` (it will be considered a write to - // every field, sensibly enough), though the borrowck - // pass will reject it later on. - // - // Also, note that, within a ctor at least, an - // expression like `self.f` is "shortcircuiting" - // before it reaches this point by the code for - // expr_field. - let ln = self.live_node(expr.id, expr.span); - if acc != 0u { - self.init_from_succ(ln, succ); - for self.ir.field_map.each_value |var| { - self.acc(ln, var, acc); - } - } - ln - } - Some(RelevantVar(nid)) => { + Some(nid) => { let ln = self.live_node(expr.id, expr.span); if acc != 0u { self.init_from_succ(ln, succ); @@ -1383,29 +1292,6 @@ impl Liveness { } } - fn as_self_field(expr: @expr, - fld: ident) -> Option<(LiveNode,Variable)> { - // If we checking a constructor, then we treat self.f as a - // variable. we use the live_node id that will be assigned to - // the reference to self but the variable id for `f`. - match expr.node { - expr_path(_) => { - let def = self.tcx.def_map.get(expr.id); - match def { - def_self(_) => { - // Note: the field_map is empty unless we are in a ctor - return self.ir.field_map.find(fld).map(|var| { - let ln = self.live_node(expr.id, expr.span); - (ln, *var) - }); - } - _ => return None - } - } - _ => return None - } - } - fn propagate_through_loop(expr: @expr, cond: Option<@expr>, body: blk, @@ -1533,7 +1419,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) { expr_fn(*) | expr_fn_block(*) => { let caps = (*self.ir).captures(expr); for (*caps).each |cap| { - let var = self.variable_from_rdef(cap.rv, expr.span); + let var = self.variable(cap.var_nid, expr.span); self.consider_last_use(expr, cap.ln, var); if cap.is_move { self.check_move_from_var(expr.span, cap.ln, var); @@ -1613,24 +1499,7 @@ enum ReadKind { } impl @Liveness { - fn check_fields(sp: span, entry_ln: LiveNode) { - for self.ir.field_map.each |nm, var| { - match self.live_on_entry(entry_ln, var) { - None => { /* ok */ } - Some(ExitNode) => { - self.tcx.sess.span_err( - sp, fmt!("field `self.%s` is never initialized", - self.tcx.sess.str_of(nm))); - } - Some(lnk) => { - self.report_illegal_read( - sp, lnk, var, PossiblyUninitializedField); - } - } - } - } - - fn check_ret(id: node_id, sp: span, fk: visit::fn_kind, + fn check_ret(id: node_id, sp: span, _fk: visit::fn_kind, entry_ln: LiveNode) { if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { // if no_ret_var is live, then we fall off the end of the @@ -1644,15 +1513,8 @@ impl @Liveness { self.tcx.sess.span_err( sp, ~"some control paths may return"); } else { - match fk { - visit::fk_ctor(*) => { - // ctors are written as though they are unit. - } - _ => { - self.tcx.sess.span_err( - sp, ~"not all control paths return a value"); - } - } + self.tcx.sess.span_err( + sp, ~"not all control paths return a value"); } } } @@ -1732,12 +1594,11 @@ impl @Liveness { } def => { match relevant_def(def) { - Some(RelevantVar(nid)) => { + Some(nid) => { let ln = self.live_node(expr.id, expr.span); let var = self.variable(nid, expr.span); self.warn_about_dead_assign(expr.span, ln, var); } - Some(RelevantSelf) => {} None => {} } } @@ -1796,13 +1657,6 @@ impl @Liveness { copy or move mode", self.tcx.sess.str_of(name))); return; } - Field(name) => { - self.tcx.sess.span_err( - move_span, - fmt!("illegal move from field `%s`", - self.tcx.sess.str_of(name))); - return; - } Self => { self.tcx.sess.span_err( move_span, diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index ff708b7f4efa..eb0bf8796f07 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -305,16 +305,16 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visitor: visit::vt) { let fn_cx = match fk { - visit::fk_item_fn(*) | visit::fk_method(*) | - visit::fk_ctor(*) | visit::fk_dtor(*) => { - // Top-level functions are a root scope. - ctxt {parent: Some(id),.. cx} - } + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => { + // Top-level functions are a root scope. + ctxt {parent: Some(id),.. cx} + } - visit::fk_anon(*) | visit::fk_fn_block(*) => { - // Closures continue with the inherited scope. - cx - } + visit::fk_anon(*) | visit::fk_fn_block(*) => { + // Closures continue with the inherited scope. + cx + } }; debug!("visiting fn with body %d. cx.parent: %? \ @@ -641,7 +641,7 @@ fn determine_rp_in_ty(ty: @ast::ty, match ty.node { ast::ty_path(path, id) => { match cx.def_map.get(id) { - ast::def_ty(did) | ast::def_class(did, _) => { + ast::def_ty(did) | ast::def_class(did) => { if did.crate == ast::local_crate { if cx.opt_region_is_relevant(path.rp) { cx.add_dep(did.node); diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 314dea1b5763..045905bbe07b 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -757,7 +757,7 @@ struct Resolver { unused_import_lint_level: level, trait_info: HashMap>, - structs: HashMap, + structs: HashMap, // The number of imports that are currently unresolved. mut unresolved_imports: uint, @@ -1069,36 +1069,15 @@ impl Resolver { } // These items live in both the type and value namespaces. - item_class(struct_definition, _) => { - let new_parent = - match struct_definition.ctor { - None => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[TypeNS], sp); + item_class(*) => { + let (name_bindings, new_parent) = + self.add_child(ident, parent, ~[TypeNS], sp); - (*name_bindings).define_type - (privacy, def_ty(local_def(item.id)), sp); - new_parent - } - Some(ctor) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[ValueNS, TypeNS], - sp); - - (*name_bindings).define_type - (privacy, def_ty(local_def(item.id)), sp); - - let purity = impure_fn; - let ctor_def = def_fn(local_def(ctor.node.id), - purity); - (*name_bindings).define_value(privacy, ctor_def, sp); - new_parent - } - }; + (*name_bindings).define_type + (privacy, def_ty(local_def(item.id)), sp); // Record the def ID of this struct. - self.structs.insert(local_def(item.id), - struct_definition.ctor.is_some()); + self.structs.insert(local_def(item.id), ()); visit_item(item, new_parent, visitor); } @@ -1184,7 +1163,7 @@ impl Resolver { def_variant(item_id, local_def(variant.node.id)), variant.span); - self.structs.insert(local_def(variant.node.id), false); + self.structs.insert(local_def(variant.node.id), ()); } enum_variant_kind(enum_definition) => { (*child).define_type(privacy, @@ -1521,18 +1500,12 @@ impl Resolver { child_name_bindings.define_type(Public, def, dummy_sp()); } - def_class(def_id, has_constructor) => { + def_class(def_id) => { debug!("(building reduced graph for external \ - crate) building type %s (value? %d)", - final_ident, - if has_constructor { 1 } else { 0 }); + crate) building type %s", + final_ident); child_name_bindings.define_type(Public, def, dummy_sp()); - - if has_constructor { - child_name_bindings.define_value(Public, def, dummy_sp()); - } - - self.structs.insert(def_id, has_constructor); + self.structs.insert(def_id, ()); } def_self(*) | def_arg(*) | def_local(*) | def_prim_ty(*) | def_ty_param(*) | def_binding(*) | @@ -3307,7 +3280,6 @@ impl Resolver { struct_def.traits, struct_def.fields, struct_def.methods, - struct_def.ctor, struct_def.dtor, visitor); } @@ -3549,7 +3521,6 @@ impl Resolver { traits: ~[@trait_ref], fields: ~[@struct_field], methods: ~[@method], - optional_constructor: Option, optional_destructor: Option, visitor: ResolveVisitor) { @@ -3601,23 +3572,6 @@ impl Resolver { self.resolve_type(field.node.ty, visitor); } - // Resolve the constructor, if applicable. - match optional_constructor { - None => { - // Nothing to do. - } - Some(constructor) => { - self.resolve_function(NormalRibKind, - Some(@constructor.node.dec), - NoTypeParameters, - constructor.node.body, - HasSelfBinding(constructor.node. - self_id), - NoCaptureClause, - visitor); - } - } - // Resolve the destructor, if applicable. match optional_destructor { None => { @@ -4090,9 +4044,7 @@ impl Resolver { match self.resolve_path(path, TypeNS, false, visitor) { Some(def_ty(class_id)) if self.structs.contains_key(class_id) => { - let has_constructor = self.structs.get(class_id); - let class_def = def_class(class_id, - has_constructor); + let class_def = def_class(class_id); self.record_def(pattern.id, class_def); } Some(definition @ def_variant(_, variant_id)) @@ -4560,10 +4512,9 @@ impl Resolver { // let bar = Bar { ... } // no type parameters match self.resolve_path(path, TypeNS, false, visitor) { - Some(def_ty(class_id)) | Some(def_class(class_id, _)) + Some(def_ty(class_id)) | Some(def_class(class_id)) if self.structs.contains_key(class_id) => { - let has_constructor = self.structs.get(class_id); - let class_def = def_class(class_id, has_constructor); + let class_def = def_class(class_id); self.record_def(expr.id, class_def); } Some(definition @ def_variant(_, class_id)) diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index aa0f11922dd0..06d5b2f239e3 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1596,18 +1596,14 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, // translation calls that don't have a return value (trans_crate, // trans_mod, trans_item, et cetera) and those that do // (trans_block, trans_expr, et cetera). - - if !ccx.class_ctors.contains_key(id) // hack -- - /* avoids the need for special cases to assign a type to - the constructor body (since it has no explicit return) */ - && - (body.node.expr.is_none() || - ty::type_is_bot(block_ty) || - ty::type_is_nil(block_ty)) { + if body.node.expr.is_none() || ty::type_is_bot(block_ty) || + ty::type_is_nil(block_ty) + { bcx = controlflow::trans_block(bcx, body, expr::Ignore); } else { bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr)); } + finish(bcx); cleanup_and_Br(bcx, bcx_top, fcx.llreturn); @@ -1698,60 +1694,6 @@ fn trans_enum_variant(ccx: @crate_ctxt, finish_fn(fcx, lltop); } -fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, - body: ast::blk, llctor_decl: ValueRef, - psubsts: param_substs, ctor_id: ast::node_id, - parent_id: ast::def_id, sp: span) { - // Add ctor to the ctor map - ccx.class_ctors.insert(ctor_id, parent_id); - - // Translate the ctor - - // Set up the type for the result of the ctor - // kludgy -- this wouldn't be necessary if the typechecker - // special-cased constructors, then we could just look up - // the ctor's return type. - let rslt_ty = ty::mk_class(ccx.tcx, parent_id, - dummy_substs(psubsts.tys)); - - // Make the fn context - let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, - Some(psubsts), Some(sp)); - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, decl.inputs); - let mut bcx_top = top_scope_block(fcx, body.info()); - let lltop = bcx_top.llbb; - let arg_tys = ty::ty_fn_args(node_id_type(bcx_top, ctor_id)); - bcx_top = copy_args_to_allocas(fcx, bcx_top, decl.inputs, - raw_llargs, arg_tys); - - // Create a temporary for `self` that we will return at the end - let selfdatum = datum::scratch_datum(bcx_top, rslt_ty, true); - - // Initialize dtor flag (if any) to 1 - if ty::ty_dtor(bcx_top.tcx(), parent_id).is_some() { - let flag = GEPi(bcx_top, selfdatum.val, [0, 1]); - Store(bcx_top, C_u8(1), flag); - } - - // initialize fields to zero - let mut bcx = bcx_top; - - // note we don't want to take *or* drop self. - fcx.llself = Some(ValSelfData {v: selfdatum.val, - t: rslt_ty, - is_owned: false}); - - // Translate the body of the ctor - bcx = controlflow::trans_block(bcx, body, expr::Ignore); - - // Generate the return expression - bcx = selfdatum.move_to(bcx, datum::INIT, fcx.llretptr); - - cleanup_and_leave(bcx, None, Some(fcx.llreturn)); - Unreachable(bcx); - finish_fn(fcx, lltop); -} - fn trans_class_dtor(ccx: @crate_ctxt, path: path, body: ast::blk, dtor_id: ast::node_id, psubsts: Option, @@ -1921,14 +1863,6 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, tps: ~[ast::ty_param], path: @ast_map::path, ident: ast::ident, id: ast::node_id) { if tps.len() == 0u { - let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps), - vtables: None, - bounds: @~[]}; - do option::iter(&struct_def.ctor) |ctor| { - trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body, - get_item_val(ccx, ctor.node.id), psubsts, - ctor.node.id, local_def(id), ctor.span); - } do option::iter(&struct_def.dtor) |dtor| { trans_class_dtor(ccx, *path, dtor.node.body, dtor.node.id, None, None, local_def(id)); @@ -2184,10 +2118,6 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { } } } - ast_map::node_ctor(nm, _, ctor, _, pt) => { - let my_path = vec::append(*pt, ~[path_name(nm)]); - register_fn(ccx, ctor.span, my_path, ctor.node.id) - } ast_map::node_dtor(_, dt, parent_id, pt) => { /* Don't just call register_fn, since we don't want to add @@ -2712,7 +2642,6 @@ fn trans_crate(sess: session::session, crate_map: crate_map, mut uses_gc: false, dbg_cx: dbg_cx, - class_ctors: HashMap(), mut do_not_commit_warning_issued: false}; diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 68e957bfe709..b87d690a1c34 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -170,11 +170,6 @@ type crate_ctxt = { // is not emitted by LLVM's GC pass when no functions use GC. mut uses_gc: bool, dbg_cx: Option, - // Mapping from class constructors to parent class -- - // used in base::trans_closure - // parent_class must be a def_id because ctors can be - // inlined, so the parent may be in a different crate - class_ctors: HashMap, mut do_not_commit_warning_issued: bool}; // Types used for llself. diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs index 6cd4b49fa3b3..068ec49d6c7e 100644 --- a/src/rustc/middle/trans/debuginfo.rs +++ b/src/rustc/middle/trans/debuginfo.rs @@ -732,10 +732,6 @@ fn create_function(fcx: fn_ctxt) -> @metadata { ast_map::node_method(method, _, _) => { (method.ident, method.decl.output, method.id) } - ast_map::node_ctor(nm, _, ctor, _, _) => { - // FIXME: output type may be wrong (#2194) - (nm, ctor.node.dec.output, ctor.node.id) - } ast_map::node_expr(expr) => { match expr.node { ast::expr_fn(_, decl, _, _) => { diff --git a/src/rustc/middle/trans/inline.rs b/src/rustc/middle/trans/inline.rs index 76888471bf97..ce9088d4b55c 100644 --- a/src/rustc/middle/trans/inline.rs +++ b/src/rustc/middle/trans/inline.rs @@ -34,10 +34,6 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) trans_item(ccx, *item); local_def(item.id) } - csearch::found(ast::ii_ctor(ctor, _, _, _)) => { - ccx.external.insert(fn_id, Some(ctor.node.id)); - local_def(ctor.node.id) - } csearch::found(ast::ii_foreign(item)) => { ccx.external.insert(fn_id, Some(item.id)); local_def(item.id) diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 87c073d567d7..914b733df198 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -5,7 +5,7 @@ use syntax::ast_map::{path, path_mod, path_name}; use base::{trans_item, get_item_val, no_self, self_arg, trans_fn, impl_self, decl_internal_cdecl_fn, set_inline_hint_if_appr, set_inline_hint, - trans_enum_variant, trans_class_ctor, trans_class_dtor, + trans_enum_variant, trans_class_dtor, get_insn_ctxt}; use syntax::parse::token::special_idents; use type_of::type_of_fn_from_ty; @@ -71,7 +71,6 @@ fn monomorphic_fn(ccx: @crate_ctxt, return {val: get_item_val(ccx, fn_id.node), must_cast: true}; } - ast_map::node_ctor(nm, _, ct, _, pt) => (pt, nm, ct.span), ast_map::node_dtor(_, dtor, _, pt) => (pt, special_idents::dtor, dtor.span), ast_map::node_trait_method(*) => { @@ -162,16 +161,6 @@ fn monomorphic_fn(ccx: @crate_ctxt, meth::trans_method(ccx, pt, mth, psubsts, None, d); d } - ast_map::node_ctor(_, tps, ctor, parent_id, _) => { - // ctors don't have attrs, at least not right now - let d = mk_lldecl(); - let tp_tys = ty::ty_params_to_tys(ccx.tcx, tps); - trans_class_ctor(ccx, pt, ctor.node.dec, ctor.node.body, d, - option::get_default(&psubsts, - {tys:tp_tys, vtables: None, bounds: @~[]}), - fn_id.node, parent_id, ctor.span); - d - } ast_map::node_dtor(_, dtor, _, pt) => { let parent_id = match ty::ty_to_def_id(ty::node_id_to_type(ccx.tcx, dtor.node.self_id)) { diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs index 3c4439c918fb..bfb8de76a6c5 100644 --- a/src/rustc/middle/trans/reachable.rs +++ b/src/rustc/middle/trans/reachable.rs @@ -59,10 +59,6 @@ fn traverse_def_id(cx: ctx, did: def_id) { cx.rmap.insert(item.id, ()); } ast_map::node_variant(v, _, _) => { cx.rmap.insert(v.node.id, ()); } - // If it's a ctor, consider the parent reachable - ast_map::node_ctor(_, _, _, parent_id, _) => { - traverse_def_id(cx, parent_id); - } _ => () } } @@ -104,13 +100,6 @@ fn traverse_public_item(cx: ctx, item: @item) { } } item_class(struct_def, tps) => { - do option::iter(&struct_def.ctor) |ctor| { - cx.rmap.insert(ctor.node.id, ()); - if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs) - != attr::ia_none { - traverse_inline_body(cx, ctor.node.body); - } - } do option::iter(&struct_def.dtor) |dtor| { cx.rmap.insert(dtor.node.id, ()); if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs) diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index ee247eb5db79..1f9ad20dd03e 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -109,9 +109,6 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;} } } - ast_map::node_ctor(_, _, ctor, _, _) => { - handle_body(cx, ctor.node.body); - } ast_map::node_dtor(_, dtor, _, _) => { handle_body(cx, dtor.node.body); } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index c1195d473aa5..cc132a431a33 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -3318,7 +3318,7 @@ fn note_and_explain_type_err(cx: ctxt, err: &type_err) { fn def_has_ty_params(def: ast::def) -> bool { match def { - ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_, _) + ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_) => true, _ => false } @@ -3492,9 +3492,6 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path { ast_map::path_name(variant.node.name)) } - ast_map::node_ctor(nm, _, _, _, path) => { - vec::append_one(*path, ast_map::path_name(nm)) - } ast_map::node_dtor(_, _, _, path) => { vec::append_one(*path, ast_map::path_name( syntax::parse::token::special_idents::literally_dtor)) diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index 14797fcdd6bb..389c1adb016b 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -323,7 +323,7 @@ fn ast_ty_to_ty( Some(d) => d }; match a_def { - ast::def_ty(did) | ast::def_class(did, _) => { + ast::def_ty(did) | ast::def_class(did) => { ast_path_to_ty(self, rscope, did, path, id).ty } ast::def_prim_ty(nty) => { diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index bf0ca36dddf4..2bf124526ac8 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -451,18 +451,6 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, let tcx = ccx.tcx; let self_ty = ty::node_id_to_type(tcx, id); - do option::iter(&struct_def.ctor) |ctor| { - let class_t = {self_ty: self_ty, - self_id: ctor.node.self_id, - def_id: local_def(id), - explicit_self: {node: ast::sty_by_ref, - span: ast_util::dummy_sp()}}; - // typecheck the ctor - check_bare_fn(ccx, ctor.node.dec, - ctor.node.body, ctor.node.id, - Some(class_t)); - } - do option::iter(&struct_def.dtor) |dtor| { let class_t = {self_ty: self_ty, self_id: dtor.node.self_id, @@ -1925,7 +1913,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Resolve the path. let class_id; match tcx.def_map.find(id) { - Some(ast::def_class(type_def_id, _)) => { + Some(ast::def_class(type_def_id)) => { class_id = type_def_id; } _ => { @@ -2411,7 +2399,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> ast::def_fn(id, _) | ast::def_static_method(id, _, _) | ast::def_const(id) | ast::def_variant(_, id) | - ast::def_class(id, _) => { + ast::def_class(id) => { return ty::lookup_item_type(fcx.ccx.tcx, id); } ast::def_upvar(_, inner, _, _) => { diff --git a/src/rustc/middle/typeck/check/alt.rs b/src/rustc/middle/typeck/check/alt.rs index 0b2e9c8ab3dd..24bcc2281fb9 100644 --- a/src/rustc/middle/typeck/check/alt.rs +++ b/src/rustc/middle/typeck/check/alt.rs @@ -325,7 +325,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { // Check to ensure that the struct is the one specified. match tcx.def_map.get(pat.id) { - ast::def_class(supplied_def_id, _) + ast::def_class(supplied_def_id) if supplied_def_id == class_id => { // OK. } diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 0a2643f6d0fe..a38e69effdff 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -497,30 +497,6 @@ fn convert_struct(ccx: @crate_ctxt, tpt: ty::ty_param_bounds_and_ty, id: ast::node_id) { let tcx = ccx.tcx; - do option::iter(&struct_def.ctor) |ctor| { - // Write the ctor type - let t_args = ctor.node.dec.inputs.map( - |a| ty_of_arg(ccx, type_rscope(rp), *a, None) ); - let t_res = ty::mk_class( - tcx, local_def(id), - {self_r: rscope::bound_self_region(rp), - self_ty: None, - tps: ty::ty_params_to_tys(tcx, tps)}); - let proto = ty::proto_vstore(ty::vstore_slice(ty::re_static)); - let t_ctor = ty::mk_fn(tcx, FnTyBase { - meta: FnMeta {purity: ast::impure_fn, - proto: proto, - bounds: @~[], - ret_style: ast::return_val}, - sig: FnSig {inputs: t_args, - output: t_res} - }); - write_ty_to_tcx(tcx, ctor.node.id, t_ctor); - tcx.tcache.insert(local_def(ctor.node.id), - {bounds: tpt.bounds, - region_param: rp, - ty: t_ctor}); - } do option::iter(&struct_def.dtor) |dtor| { // Write the dtor type diff --git a/src/test/compile-fail/cap-clause-use-after-move.rs b/src/test/compile-fail/cap-clause-use-after-move.rs index 7fb06ba5a23a..a19dfc9e9f4a 100644 --- a/src/test/compile-fail/cap-clause-use-after-move.rs +++ b/src/test/compile-fail/cap-clause-use-after-move.rs @@ -1,7 +1,5 @@ -// error-pattern:Unsatisfied precondition constraint - fn main() { let x = 5; - let _y = fn~(move x) { }; - let _z = x; //< error: Unsatisfied precondition constraint + let _y = fn~(move x) { }; //~ WARNING captured variable `x` not used in closure + let _z = x; //~ ERROR use of moved variable: `x` } diff --git a/src/test/compile-fail/issue-2590.rs b/src/test/compile-fail/issue-2590.rs index f4ccd901fb3a..0f4a4804c751 100644 --- a/src/test/compile-fail/issue-2590.rs +++ b/src/test/compile-fail/issue-2590.rs @@ -10,7 +10,7 @@ trait parse { impl parser: parse { fn parse() -> ~[int] { - dvec::unwrap(move self.tokens) //~ ERROR illegal move from self + dvec::unwrap(move self.tokens) //~ ERROR moving out of immutable field } } diff --git a/src/test/compile-fail/regions-glb-free-free.rs b/src/test/compile-fail/regions-glb-free-free.rs index 223665381da1..e4913f7056e8 100644 --- a/src/test/compile-fail/regions-glb-free-free.rs +++ b/src/test/compile-fail/regions-glb-free-free.rs @@ -19,7 +19,7 @@ mod argparse { fn set_desc(self, s: &str) -> Flag { Flag { //~ ERROR cannot infer an appropriate lifetime name: self.name, - desc: s, + desc: s, //~ ERROR cannot infer an appropriate lifetime max_count: self.max_count, value: self.value } From 335e5ca33b606ce46e636c68fb85f486d4185717 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:36:02 -0700 Subject: [PATCH 176/292] Add a colon, make an error message clearer --- src/libsyntax/ext/tt/macro_parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 16e3454ca2c4..0b2070c8c86d 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -345,7 +345,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) built-in NTs %s or %u other options.", nts, next_eis.len())); } else if (bb_eis.len() == 0u && next_eis.len() == 0u) { - return failure(sp, ~"No rules expected the token " + return failure(sp, ~"No rules expected the token: " + to_str(rdr.interner(), tok)); } else if (next_eis.len() > 0u) { /* Now process the next token */ From c5fa61349894282f9b9a367e08ede0ca4ef67a75 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 12 Oct 2012 17:55:28 -0700 Subject: [PATCH 177/292] Make moves explicit in libsyntax --- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/util/interner.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 94bf2a43f28a..5894758cd85c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -231,7 +231,7 @@ fn mk_ctxt(parse_sess: parse::parse_sess, mut mod_path: ~[], mut trace_mac: false }; - move (imp as ext_ctxt) + move ((move imp) as ext_ctxt) } fn expr_to_str(cx: ext_ctxt, expr: @ast::expr, error: ~str) -> ~str { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 021c25e3dd71..5d991bb3551c 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -16,7 +16,7 @@ fn mk() -> interner { let m = map::HashMap::(); let hi: hash_interner = {map: m, vect: DVec()}; - move (hi as interner::) + move ((move hi) as interner::) } fn mk_prefill(init: ~[T]) -> interner { From d0ed13c4bdb19b2e9c445908775794f0880a301c Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 12 Oct 2012 18:02:02 -0700 Subject: [PATCH 178/292] Make moves explicit in rustc::middle --- src/rustc/middle/trans/alt.rs | 2 +- src/rustc/middle/trans/common.rs | 2 +- src/rustc/middle/typeck/infer/combine.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index 73f1e9bd1191..50ea80a134cb 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -1202,7 +1202,7 @@ fn trans_alt_inner(scope_cx: block, arm_cxs.push(bcx); } - return controlflow::join_blocks(scope_cx, dvec::unwrap(arm_cxs)); + return controlflow::join_blocks(scope_cx, dvec::unwrap(move arm_cxs)); fn mk_fail(bcx: block, sp: span, msg: ~str, done: @mut Option) -> BasicBlockRef { diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index b87d690a1c34..61141f18336f 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -511,7 +511,7 @@ fn block_(llbb: BasicBlockRef, parent: Option, -kind: block_kind, terminated: false, unreachable: false, parent: parent, - kind: kind, + kind: move kind, is_lpad: is_lpad, node_info: node_info, fcx: fcx diff --git a/src/rustc/middle/typeck/infer/combine.rs b/src/rustc/middle/typeck/infer/combine.rs index db65bff9bfec..bdda45c1168a 100644 --- a/src/rustc/middle/typeck/infer/combine.rs +++ b/src/rustc/middle/typeck/infer/combine.rs @@ -88,9 +88,9 @@ fn expected_found( self: &C, +a: T, +b: T) -> ty::expected_found { if self.a_is_expected() { - ty::expected_found {expected: a, found: b} + ty::expected_found {expected: move a, found: move b} } else { - ty::expected_found {expected: b, found: a} + ty::expected_found {expected: move b, found: move a} } } From ea5e3d21ff5ef8b4d30b588d0cd65859ffa3bab1 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:33:49 -0700 Subject: [PATCH 179/292] Make moves explicit in doc examples Had to remove the buffalo example. It was awkward to update for explicit moves. --- doc/tutorial-tasks.md | 18 +++++++++--------- doc/tutorial.md | 2 +- src/test/run-pass/issue-3668.rs | 13 +++++++++++++ src/test/run-pass/issue-3688-2.rs | 5 +++++ 4 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 src/test/run-pass/issue-3668.rs create mode 100644 src/test/run-pass/issue-3688-2.rs diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md index 8a0cda3e8207..2d203400dda8 100644 --- a/doc/tutorial-tasks.md +++ b/doc/tutorial-tasks.md @@ -161,7 +161,7 @@ use pipes::{stream, Port, Chan}; let (chan, port): (Chan, Port) = stream(); -do spawn { +do spawn |move chan| { let result = some_expensive_computation(); chan.send(result); } @@ -192,7 +192,7 @@ spawns the child task. # use pipes::{stream, Port, Chan}; # fn some_expensive_computation() -> int { 42 } # let (chan, port) = stream(); -do spawn { +do spawn |move chan| { let result = some_expensive_computation(); chan.send(result); } @@ -229,7 +229,7 @@ following program is ill-typed: # fn some_expensive_computation() -> int { 42 } let (chan, port) = stream(); -do spawn { +do spawn |move chan| { chan.send(some_expensive_computation()); } @@ -253,7 +253,7 @@ let chan = SharedChan(move chan); for uint::range(0, 3) |init_val| { // Create a new channel handle to distribute to the child task let child_chan = chan.clone(); - do spawn { + do spawn |move child_chan| { child_chan.send(some_expensive_computation(init_val)); } } @@ -283,10 +283,10 @@ might look like the example below. // Create a vector of ports, one for each child task let ports = do vec::from_fn(3) |init_val| { let (chan, port) = stream(); - do spawn { + do spawn |move chan| { chan.send(some_expensive_computation(init_val)); } - port + move port }; // Wait on each port, accumulating the results @@ -398,13 +398,13 @@ before returning. Hence: # fn sleep_forever() { loop { task::yield() } } # do task::try { let (sender, receiver): (Chan, Port) = stream(); -do spawn { // Bidirectionally linked +do spawn |move receiver| { // Bidirectionally linked // Wait for the supervised child task to exist. let message = receiver.recv(); // Kill both it and the parent task. assert message != 42; } -do try { // Unidirectionally linked +do try |move sender| { // Unidirectionally linked sender.send(42); sleep_forever(); // Will get woken up by force } @@ -505,7 +505,7 @@ Here is the code for the parent task: let (from_child, to_child) = DuplexStream(); -do spawn || { +do spawn |move to_child| { stringifier(&to_child); }; diff --git a/doc/tutorial.md b/doc/tutorial.md index 12850a92a038..8746cf026f9e 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1827,7 +1827,7 @@ fn map(vector: &[T], function: fn(v: &T) -> U) -> ~[U] { for vec::each(vector) |element| { accumulator.push(function(element)); } - return accumulator; + return (move accumulator); } ~~~~ diff --git a/src/test/run-pass/issue-3668.rs b/src/test/run-pass/issue-3668.rs new file mode 100644 index 000000000000..5f677767240d --- /dev/null +++ b/src/test/run-pass/issue-3668.rs @@ -0,0 +1,13 @@ +struct P { child: Option<@mut P> } +trait PTrait { + fn getChildOption() -> Option<@P>; +} + +impl P: PTrait { + fn getChildOption() -> Option<@P> { + const childVal: @P = self.child.get(); + fail; + } +} + +fn main() {} diff --git a/src/test/run-pass/issue-3688-2.rs b/src/test/run-pass/issue-3688-2.rs new file mode 100644 index 000000000000..018bd1d2a8d3 --- /dev/null +++ b/src/test/run-pass/issue-3688-2.rs @@ -0,0 +1,5 @@ + fn f(x:int) { + const child: int = x + 1; + } + +fn main() {} From beb74710167fed2ac944dc84e2403ad0c410cb94 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:34:49 -0700 Subject: [PATCH 180/292] Make moves explicit in cargo --- src/cargo/cargo.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index e5ca758ebf4e..5f39eb6b960e 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -705,7 +705,7 @@ fn configure(opts: Options) -> Cargo { ~" or package manager to get it to work correctly"); } - c + move c } fn for_each_package(c: &Cargo, b: fn(s: @Source, p: &Package)) { @@ -1615,10 +1615,10 @@ fn dump_sources(c: &Cargo) { _ => () } - hash.insert(copy k, json::Object(chash)); + hash.insert(copy k, json::Object(move chash)); } - json::to_writer(writer, &json::Object(hash)) + json::to_writer(writer, &json::Object(move hash)) } result::Err(e) => { error(fmt!("could not dump sources: %s", e)); From 2d7d12b902a9f6237994f74888878220cb2ffbed Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:35:00 -0700 Subject: [PATCH 181/292] Make moves explicit in compiletest --- src/compiletest/compiletest.rs | 2 +- src/compiletest/procsrv.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 55fa67402687..e147ddc3ed7f 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -145,7 +145,7 @@ fn make_tests(config: config) -> ~[test::TestDesc] { tests.push(make_test(config, file)) } } - return tests; + move tests } fn is_test(config: config, testfile: &Path) -> bool { diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index b03c3bbf42fa..38102e9af35b 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -60,12 +60,12 @@ fn run(lib_path: ~str, writeclose(pipe_in.out, input); let p = pipes::PortSet(); let ch = p.chan(); - do task::spawn_sched(task::SingleThreaded) { + do task::spawn_sched(task::SingleThreaded) |move ch| { let errput = readclose(pipe_err.in); ch.send((2, errput)); } let ch = p.chan(); - do task::spawn_sched(task::SingleThreaded) { + do task::spawn_sched(task::SingleThreaded) |move ch| { let output = readclose(pipe_out.in); ch.send((1, output)); } From 30a62793fa54a413a265591879c9775b798d762c Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:35:28 -0700 Subject: [PATCH 182/292] Make moves explicit in core tests --- src/libcore/cast.rs | 4 ++-- src/libcore/cleanup.rs | 2 +- src/libcore/extfmt.rs | 14 ++++++------ src/libcore/future.rs | 6 ++--- src/libcore/hash.rs | 2 +- src/libcore/io.rs | 4 ++-- src/libcore/mutable.rs | 4 ++-- src/libcore/option.rs | 12 +++++----- src/libcore/os.rs | 10 ++++----- src/libcore/path.rs | 47 +++++++++++++++++++++++++++------------ src/libcore/pipes.rs | 14 ++++++++---- src/libcore/private.rs | 40 +++++++++++++++++---------------- src/libcore/repr.rs | 6 ++--- src/libcore/result.rs | 2 +- src/libcore/run.rs | 6 ++--- src/libcore/send_map.rs | 20 ++++++++--------- src/libcore/str.rs | 32 +++++++++++++------------- src/libcore/sys.rs | 4 ++-- src/libcore/task.rs | 47 ++++++++++++++++++++++----------------- src/libcore/task/spawn.rs | 14 ++++++------ src/libcore/util.rs | 2 +- src/libcore/vec.rs | 32 +++++++++++++------------- 22 files changed, 178 insertions(+), 146 deletions(-) diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs index 030f05c6eeae..9aaf373869c8 100644 --- a/src/libcore/cast.rs +++ b/src/libcore/cast.rs @@ -122,9 +122,9 @@ pub mod tests { pub fn test_transmute() { unsafe { let x = @1; - let x: *int = transmute(x); + let x: *int = transmute(move x); assert *x == 1; - let _x: @int = transmute(x); + let _x: @int = transmute(move x); } } diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs index df6074e32009..9a3b40757a70 100644 --- a/src/libcore/cleanup.rs +++ b/src/libcore/cleanup.rs @@ -142,7 +142,7 @@ pub unsafe fn annihilate() { assert (*box).header.prev == null(); debug!("freeing box: %x", box as uint); - rt_free(transmute(box)); + rt_free(transmute(move box)); } } diff --git a/src/libcore/extfmt.rs b/src/libcore/extfmt.rs index de2e91b2e326..5acb45fdf1a5 100644 --- a/src/libcore/extfmt.rs +++ b/src/libcore/extfmt.rs @@ -301,7 +301,7 @@ pub mod rt { unsafe { str::unshift_char(&mut s, ' ') }; } } - return unsafe { pad(cv, s, PadSigned) }; + return unsafe { pad(cv, move s, PadSigned) }; } pub pure fn conv_uint(cv: Conv, u: uint) -> ~str { let prec = get_int_precision(cv); @@ -313,7 +313,7 @@ pub mod rt { TyBits => uint_to_str_prec(u, 2u, prec), TyOctal => uint_to_str_prec(u, 8u, prec) }; - return unsafe { pad(cv, rs, PadUnsigned) }; + return unsafe { pad(cv, move rs, PadUnsigned) }; } pub pure fn conv_bool(cv: Conv, b: bool) -> ~str { let s = if b { ~"true" } else { ~"false" }; @@ -323,7 +323,7 @@ pub mod rt { } pub pure fn conv_char(cv: Conv, c: char) -> ~str { let mut s = str::from_char(c); - return unsafe { pad(cv, s, PadNozero) }; + return unsafe { pad(cv, move s, PadNozero) }; } pub pure fn conv_str(cv: Conv, s: &str) -> ~str { // For strings, precision is the maximum characters @@ -336,7 +336,7 @@ pub mod rt { s.to_unique() } }; - return unsafe { pad(cv, unpadded, PadNozero) }; + return unsafe { pad(cv, move unpadded, PadNozero) }; } pub pure fn conv_float(cv: Conv, f: float) -> ~str { let (to_str, digits) = match cv.precision { @@ -351,7 +351,7 @@ pub mod rt { s = ~" " + s; } } - return unsafe { pad(cv, s, PadFloat) }; + return unsafe { pad(cv, move s, PadFloat) }; } pub pure fn conv_poly(cv: Conv, v: &T) -> ~str { let s = sys::log_str(v); @@ -411,14 +411,14 @@ pub mod rt { pub fn pad(cv: Conv, s: ~str, mode: PadMode) -> ~str { let mut s = move s; // sadtimes let uwidth : uint = match cv.width { - CountImplied => return s, + CountImplied => return (move s), CountIs(width) => { // FIXME: width should probably be uint (see Issue #1996) width as uint } }; let strlen = str::char_len(s); - if uwidth <= strlen { return s; } + if uwidth <= strlen { return (move s); } let mut padchar = ' '; let diff = uwidth - strlen; if have_flag(cv.flags, flag_left_justify) { diff --git a/src/libcore/future.rs b/src/libcore/future.rs index efd5ff65aa5f..bc35dafde352 100644 --- a/src/libcore/future.rs +++ b/src/libcore/future.rs @@ -179,8 +179,8 @@ pub mod test { #[test] pub fn test_from_port() { let (po, ch) = future_pipe::init(); - future_pipe::server::completed(ch, ~"whale"); - let f = from_port(po); + future_pipe::server::completed(move ch, ~"whale"); + let f = from_port(move po); assert get(&f) == ~"whale"; } @@ -238,7 +238,7 @@ pub mod test { pub fn test_sendable_future() { let expected = ~"schlorf"; let f = do spawn |copy expected| { copy expected }; - do task::spawn { + do task::spawn |move f, move expected| { let actual = get(&f); assert actual == expected; } diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index 6703006650b0..1b4996a683d1 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -438,7 +438,7 @@ pub fn test_siphash() { for vec::each(*r) |b| { s += uint::to_str(*b as uint, 16u); } - return s; + move s } while t < 64 { diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 865b8013fb04..fd0fcbbe1c1f 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -737,7 +737,7 @@ pub fn BytesWriter() -> BytesWriter { pub fn with_bytes_writer(f: fn(Writer)) -> ~[u8] { let wr = @BytesWriter(); f(wr as Writer); - wr.buf.check_out(|buf| buf) + wr.buf.check_out(|buf| move buf) } pub fn with_str_writer(f: fn(Writer)) -> ~str { @@ -747,7 +747,7 @@ pub fn with_str_writer(f: fn(Writer)) -> ~str { v.push(0); assert str::is_utf8(v); - unsafe { move ::cast::transmute(v) } + unsafe { move ::cast::transmute(move v) } } // Utility functions diff --git a/src/libcore/mutable.rs b/src/libcore/mutable.rs index b314ad61ee2a..56a6df2c4ddf 100644 --- a/src/libcore/mutable.rs +++ b/src/libcore/mutable.rs @@ -24,7 +24,7 @@ struct Data { pub type Mut = Data; pub fn Mut(t: T) -> Mut { - Data {value: t, mode: ReadOnly} + Data {value: move t, mode: ReadOnly} } pub fn unwrap(m: Mut) -> T { @@ -32,7 +32,7 @@ pub fn unwrap(m: Mut) -> T { // is in use, as that would be a move from a borrowed value. assert (m.mode as uint) == (ReadOnly as uint); let Data {value: move value, mode: _} = move m; - return value; + move value } impl Data { diff --git a/src/libcore/option.rs b/src/libcore/option.rs index e970f00c5fbb..f8bafe29fdde 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -120,7 +120,7 @@ pub pure fn chain(opt: Option, */ match move opt { - Some(move t) => f(t), + Some(move t) => f(move t), None => None } } @@ -294,7 +294,7 @@ impl Option { * * Fails if the value equals `none` */ - pure fn expect(reason: ~str) -> T { expect(&self, reason) } + pure fn expect(reason: ~str) -> T { expect(&self, move reason) } /// Applies a function zero or more times until the result is none. pure fn while_some(blk: fn(v: T) -> Option) { while_some(self, blk) } } @@ -324,8 +324,8 @@ impl Option : Eq { fn test_unwrap_ptr() { let x = ~0; let addr_x = ptr::addr_of(&(*x)); - let opt = Some(x); - let y = unwrap(opt); + let opt = Some(move x); + let y = unwrap(move opt); let addr_y = ptr::addr_of(&(*y)); assert addr_x == addr_y; } @@ -356,8 +356,8 @@ fn test_unwrap_resource() { let i = @mut 0; { let x = R(i); - let opt = Some(x); - let _y = unwrap(opt); + let opt = Some(move x); + let _y = unwrap(move opt); } assert *i == 1; } diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 3fd98e7f2987..24e4d7eff41f 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -739,7 +739,7 @@ unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] { for uint::range(0, argc as uint) |i| { vec::push(&mut args, str::raw::from_c_str(*argv.offset(i))); } - return args; + move args } /** @@ -903,7 +903,7 @@ mod tests { let rng: rand::Rng = rand::Rng(); let n = ~"TEST" + rng.gen_str(10u); assert getenv(n).is_none(); - n + move n } #[test] @@ -937,7 +937,7 @@ mod tests { let n = make_rand_name(); setenv(n, s); log(debug, s); - assert getenv(n) == option::Some(s); + assert getenv(n) == option::Some(move s); } #[test] @@ -963,7 +963,7 @@ mod tests { // MingW seems to set some funky environment variables like // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned // from env() but not visible from getenv(). - assert v2.is_none() || v2 == option::Some(v); + assert v2.is_none() || v2 == option::Some(move v); } } @@ -976,7 +976,7 @@ mod tests { assert !vec::contains(e, &(copy n, ~"VALUE")); e = env(); - assert vec::contains(e, &(n, ~"VALUE")); + assert vec::contains(e, &(move n, ~"VALUE")); } #[test] diff --git a/src/libcore/path.rs b/src/libcore/path.rs index e5d2397da0d7..871e803ff1a5 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -96,7 +96,7 @@ impl PosixPath : GenericPath { let mut components = str::split_nonempty(s, |c| c == '/'); let is_absolute = (s.len() != 0 && s[0] == '/' as u8); return PosixPath { is_absolute: is_absolute, - components: components } + components: move components } } pure fn dirname() -> ~str { @@ -192,7 +192,7 @@ impl PosixPath : GenericPath { Some(ref f) => ~[copy *f] }; return PosixPath { is_absolute: false, - components: cs } + components: move cs } } pure fn push_rel(other: &PosixPath) -> PosixPath { @@ -208,7 +208,8 @@ impl PosixPath : GenericPath { |c| windows::is_sep(c as u8)); unsafe { v.push_all_move(move ss); } } - PosixPath { components: move v, ..self } + PosixPath { is_absolute: self.is_absolute, + components: move v } } pure fn push(s: &str) -> PosixPath { @@ -223,13 +224,18 @@ impl PosixPath : GenericPath { if cs.len() != 0 { unsafe { cs.pop(); } } - return PosixPath { components: move cs, ..self } + return PosixPath { + is_absolute: self.is_absolute, + components: move cs + } + //..self } } pure fn normalize() -> PosixPath { return PosixPath { - components: normalize(self.components), - ..self + is_absolute: self.is_absolute, + components: normalize(self.components) + // ..self } } } @@ -286,10 +292,10 @@ impl WindowsPath : GenericPath { let mut components = str::split_nonempty(rest, |c| windows::is_sep(c as u8)); let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0])); - return WindowsPath { host: host, - device: device, + return WindowsPath { host: move host, + device: move device, is_absolute: is_absolute, - components: components } + components: move components } } pure fn dirname() -> ~str { @@ -386,7 +392,7 @@ impl WindowsPath : GenericPath { return WindowsPath { host: None, device: None, is_absolute: false, - components: cs } + components: move cs } } pure fn push_rel(other: &WindowsPath) -> WindowsPath { @@ -402,7 +408,13 @@ impl WindowsPath : GenericPath { |c| windows::is_sep(c as u8)); unsafe { v.push_all_move(move ss); } } - return WindowsPath { components: move v, ..self } + // tedious, but as-is, we can't use ..self + return WindowsPath { + host: copy self.host, + device: copy self.device, + is_absolute: self.is_absolute, + components: move v + } } pure fn push(s: &str) -> WindowsPath { @@ -417,13 +429,20 @@ impl WindowsPath : GenericPath { if cs.len() != 0 { unsafe { cs.pop(); } } - return WindowsPath { components: move cs, ..self } + return WindowsPath { + host: copy self.host, + device: copy self.device, + is_absolute: self.is_absolute, + components: move cs + } } pure fn normalize() -> WindowsPath { return WindowsPath { - components: normalize(self.components), - ..self + host: copy self.host, + device: copy self.device, + is_absolute: self.is_absolute, + components: normalize(self.components) } } } diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 791c6bccde8c..e77cb69b0565 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -350,7 +350,8 @@ fn BufferResource(b: ~Buffer) -> BufferResource { atomic_add_acq(&mut b.header.ref_count, 1); BufferResource { - buffer: b + // tjc: ???? + buffer: move b } } @@ -448,7 +449,12 @@ pub fn try_recv(p: RecvPacketBuffered) let this = rustrt::rust_get_task(); rustrt::task_clear_event_reject(this); rustrt::rust_task_ref(this); + debug!("blocked = %x this = %x", p.header.blocked_task as uint, + this as uint); let old_task = swap_task(&mut p.header.blocked_task, this); + debug!("blocked = %x this = %x old_task = %x", + p.header.blocked_task as uint, + this as uint, old_task as uint); assert old_task.is_null(); let mut first = true; let mut count = SPIN_COUNT; @@ -1212,7 +1218,7 @@ pub mod test { c1.send(~"abc"); - match (p1, p2).select() { + match (move p1, move p2).select() { Right(_) => fail, _ => () } @@ -1224,8 +1230,8 @@ pub mod test { pub fn test_oneshot() { let (c, p) = oneshot::init(); - oneshot::client::send(c, ()); + oneshot::client::send(move c, ()); - recv_one(p) + recv_one(move p) } } diff --git a/src/libcore/private.rs b/src/libcore/private.rs index b7be29d8fbdc..a54db3fa759b 100644 --- a/src/libcore/private.rs +++ b/src/libcore/private.rs @@ -374,7 +374,7 @@ pub unsafe fn unwrap_shared_mutable_state(rc: SharedMutableState) rc.data = ptr::null(); // Step 1 - drop our own reference. let new_count = rustrt::rust_atomic_decrement(&mut ptr.count); - assert new_count >= 0; + // assert new_count >= 0; if new_count == 0 { // We were the last owner. Can unwrap immediately. // Also we have to free the server endpoints. @@ -505,7 +505,7 @@ pub struct Exclusive { x: SharedMutableState> } pub fn exclusive(user_data: T) -> Exclusive { let data = ExData { - lock: LittleLock(), mut failed: false, mut data: user_data + lock: LittleLock(), mut failed: false, mut data: move user_data }; Exclusive { x: unsafe { shared_mutable_state(move data) } } } @@ -558,17 +558,17 @@ pub mod tests { pub fn exclusive_arc() { let mut futures = ~[]; - let num_tasks = 10u; - let count = 10u; + let num_tasks = 10; + let count = 10; - let total = exclusive(~mut 0u); + let total = exclusive(~mut 0); - for uint::range(0u, num_tasks) |_i| { + for uint::range(0, num_tasks) |_i| { let total = total.clone(); - futures.push(future::spawn(|| { - for uint::range(0u, count) |_i| { + futures.push(future::spawn(|move total| { + for uint::range(0, count) |_i| { do total.with |count| { - **count += 1u; + **count += 1; } } })); @@ -587,7 +587,7 @@ pub mod tests { // accesses will also fail. let x = exclusive(1); let x2 = x.clone(); - do task::try { + do task::try |move x2| { do x2.with |one| { assert *one == 2; } @@ -600,27 +600,28 @@ pub mod tests { #[test] pub fn exclusive_unwrap_basic() { let x = exclusive(~~"hello"); - assert unwrap_exclusive(x) == ~~"hello"; + assert unwrap_exclusive(move x) == ~~"hello"; } #[test] pub fn exclusive_unwrap_contended() { let x = exclusive(~~"hello"); let x2 = ~mut Some(x.clone()); - do task::spawn { + do task::spawn |move x2| { let x2 = option::swap_unwrap(x2); do x2.with |_hello| { } task::yield(); } - assert unwrap_exclusive(x) == ~~"hello"; + assert unwrap_exclusive(move x) == ~~"hello"; // Now try the same thing, but with the child task blocking. let x = exclusive(~~"hello"); let x2 = ~mut Some(x.clone()); let mut res = None; - do task::task().future_result(|+r| res = Some(r)).spawn { + do task::task().future_result(|+r| res = Some(move r)).spawn + |move x2| { let x2 = option::swap_unwrap(x2); - assert unwrap_exclusive(x2) == ~~"hello"; + assert unwrap_exclusive(move x2) == ~~"hello"; } // Have to get rid of our reference before blocking. { let _x = move x; } // FIXME(#3161) util::ignore doesn't work here @@ -633,11 +634,12 @@ pub mod tests { let x = exclusive(~~"hello"); let x2 = ~mut Some(x.clone()); let mut res = None; - do task::task().future_result(|+r| res = Some(r)).spawn { + do task::task().future_result(|+r| res = Some(move r)).spawn + |move x2| { let x2 = option::swap_unwrap(x2); - assert unwrap_exclusive(x2) == ~~"hello"; + assert unwrap_exclusive(move x2) == ~~"hello"; } - assert unwrap_exclusive(x) == ~~"hello"; + assert unwrap_exclusive(move x) == ~~"hello"; let res = option::swap_unwrap(&mut res); future::get(&res); } @@ -656,7 +658,7 @@ pub mod tests { for 10.times { task::yield(); } // try to let the unwrapper go fail; // punt it awake from its deadlock } - let _z = unwrap_exclusive(x); + let _z = unwrap_exclusive(move x); do x2.with |_hello| { } }; assert result.is_err(); diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 2003949d6314..ff29953f09a4 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -156,7 +156,7 @@ impl ReprVisitor { fn visit_ptr_inner(ptr: *c_void, inner: *TyDesc) -> bool { let mut u = ReprVisitor(ptr, self.writer); let v = reflect::MovePtrAdaptor(move u); - visit_tydesc(inner, v as @TyVisitor); + visit_tydesc(inner, (move v) as @TyVisitor); true } @@ -453,7 +453,7 @@ pub fn write_repr2(writer: @Writer, object: &T) { let tydesc = intrinsic::get_tydesc::(); let mut u = ReprVisitor(ptr, writer); let v = reflect::MovePtrAdaptor(move u); - visit_tydesc(tydesc, v as @TyVisitor) + visit_tydesc(tydesc, (move v) as @TyVisitor) } #[test] @@ -992,7 +992,7 @@ pub fn write_repr(writer: @Writer, object: &T) { unsafe { let ptr = ptr::to_unsafe_ptr(object) as *c_void; let tydesc = sys::get_type_desc::(); - let tydesc = cast::transmute(tydesc); + let tydesc = cast::transmute(move tydesc); let repr_printer = @ReprPrinter { ptr: ptr, diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 611d62394357..06d8c0da0d01 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -106,7 +106,7 @@ pub pure fn to_either(res: &Result) pub fn chain(res: Result, op: fn(t: T) -> Result) -> Result { match move res { - Ok(move t) => op(t), + Ok(move t) => op(move t), Err(move e) => Err(e) } } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 0ff917492091..06b869306305 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -226,7 +226,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> Program { fn ProgRes(r: ProgRepr) -> ProgRes { ProgRes { - r: r + r: move r } } @@ -313,10 +313,10 @@ pub fn program_output(prog: &str, args: &[~str]) -> let stream = comm::recv(p); match stream { (1, copy s) => { - outs = s; + outs = move s; } (2, copy s) => { - errs = s; + errs = move s; } (n, _) => { fail(fmt!("program_output received an unexpected file \ diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs index d275069a14b5..58b35b82a31f 100644 --- a/src/libcore/send_map.rs +++ b/src/libcore/send_map.rs @@ -185,8 +185,8 @@ pub mod linear { debug!("insert fresh (%?->%?) at idx %?, hash %?", k, v, idx, hash); self.buckets[idx] = Some(Bucket {hash: hash, - key: k, - value: v}); + key: move k, + value: move v}); self.size += 1; true } @@ -194,8 +194,8 @@ pub mod linear { debug!("insert overwrite (%?->%?) at idx %?, hash %?", k, v, idx, hash); self.buckets[idx] = Some(Bucket {hash: hash, - key: k, - value: v}); + key: move k, + value: move v}); false } } @@ -230,7 +230,7 @@ pub mod linear { None => None, Some(move bucket) => { let Bucket { value: move value, _ } = move bucket; - Some(value) + Some(move value) }, }; @@ -243,7 +243,7 @@ pub mod linear { } self.size -= 1; - value + move value } @@ -297,9 +297,9 @@ pub mod linear { self.expand(); } - self.insert_internal(hash, k, v); + self.insert_internal(hash, move k, move v); - old_value + move old_value } fn consume(&mut self, f: fn(K, V)) { @@ -307,7 +307,7 @@ pub mod linear { self.buckets <-> buckets; self.size = 0; - do vec::consume(buckets) |_i, bucket| { + do vec::consume(move buckets) |_i, bucket| { match move bucket { None => { }, Some(move bucket) => { @@ -316,7 +316,7 @@ pub mod linear { value: move value, _ } = move bucket; - f(key, value) + f(move key, move value) } } } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index aff4c50cfd2d..677a33d56c0d 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2562,23 +2562,23 @@ mod tests { #[test] fn test_unsafe_slice() { unsafe { - assert ~"ab" == raw::slice_bytes(~"abc", 0u, 2u); - assert ~"bc" == raw::slice_bytes(~"abc", 1u, 3u); - assert ~"" == raw::slice_bytes(~"abc", 1u, 1u); + assert ~"ab" == raw::slice_bytes(~"abc", 0, 2); + assert ~"bc" == raw::slice_bytes(~"abc", 1, 3); + assert ~"" == raw::slice_bytes(~"abc", 1, 1); fn a_million_letter_a() -> ~str { let mut i = 0; let mut rs = ~""; while i < 100000 { push_str(&mut rs, ~"aaaaaaaaaa"); i += 1; } - return rs; + move rs } fn half_a_million_letter_a() -> ~str { let mut i = 0; let mut rs = ~""; while i < 100000 { push_str(&mut rs, ~"aaaaa"); i += 1; } - return rs; + move rs } assert half_a_million_letter_a() == - raw::slice_bytes(a_million_letter_a(), 0u, 500000u); + raw::slice_bytes(a_million_letter_a(), 0u, 500000); } } @@ -2664,16 +2664,16 @@ mod tests { #[test] fn test_slice() { - assert ~"ab" == slice(~"abc", 0u, 2u); - assert ~"bc" == slice(~"abc", 1u, 3u); - assert ~"" == slice(~"abc", 1u, 1u); - assert ~"\u65e5" == slice(~"\u65e5\u672c", 0u, 3u); + assert ~"ab" == slice(~"abc", 0, 2); + assert ~"bc" == slice(~"abc", 1, 3); + assert ~"" == slice(~"abc", 1, 1); + assert ~"\u65e5" == slice(~"\u65e5\u672c", 0, 3); let data = ~"ประเทศไทย中华"; - assert ~"ป" == slice(data, 0u, 3u); - assert ~"ร" == slice(data, 3u, 6u); - assert ~"" == slice(data, 3u, 3u); - assert ~"华" == slice(data, 30u, 33u); + assert ~"ป" == slice(data, 0, 3); + assert ~"ร" == slice(data, 3, 6); + assert ~"" == slice(data, 3, 3); + assert ~"华" == slice(data, 30, 33); fn a_million_letter_X() -> ~str { let mut i = 0; @@ -2682,13 +2682,13 @@ mod tests { push_str(&mut rs, ~"华华华华华华华华华华"); i += 1; } - return rs; + move rs } fn half_a_million_letter_X() -> ~str { let mut i = 0; let mut rs = ~""; while i < 100000 { push_str(&mut rs, ~"华华华华华"); i += 1; } - return rs; + move rs } assert half_a_million_letter_X() == slice(a_million_letter_X(), 0u, 3u * 500000u); diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 12329616fbf9..32a6987a672a 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -153,7 +153,7 @@ pub mod tests { assert f(20) == 30; - let original_closure: Closure = cast::transmute(f); + let original_closure: Closure = cast::transmute(move f); let actual_function_pointer = original_closure.code; let environment = original_closure.env; @@ -163,7 +163,7 @@ pub mod tests { env: environment }; - let new_f: fn(int) -> int = cast::transmute(new_closure); + let new_f: fn(int) -> int = cast::transmute(move new_closure); assert new_f(20) == 30; } } diff --git a/src/libcore/task.rs b/src/libcore/task.rs index afc4a821bb6d..d9e213c7f55e 100644 --- a/src/libcore/task.rs +++ b/src/libcore/task.rs @@ -424,7 +424,11 @@ impl TaskBuilder { mut notify_chan: move notify_chan, sched: self.opts.sched }, - gen_body: |body| { wrapper(prev_gen_body(move body)) }, + // tjc: I think this is the line that gets miscompiled + // w/ last-use off, if we leave out the move prev_gen_body? + // that makes no sense, though... + gen_body: |move prev_gen_body, + body| { wrapper(prev_gen_body(move body)) }, can_not_copy: None, .. *self.consume() }) @@ -931,7 +935,7 @@ fn test_add_wrapper() { let ch = comm::Chan(&po); let b0 = task(); let b1 = do b0.add_wrapper |body| { - fn~() { + fn~(move body) { body(); comm::send(ch, ()); } @@ -944,14 +948,15 @@ fn test_add_wrapper() { #[ignore(cfg(windows))] fn test_future_result() { let mut result = None; - do task().future_result(|+r| { result = Some(r); }).spawn { } - assert future::get(&option::unwrap(result)) == Success; + do task().future_result(|+r| { result = Some(move r); }).spawn { } + assert future::get(&option::unwrap(move result)) == Success; result = None; - do task().future_result(|+r| { result = Some(r); }).unlinked().spawn { + do task().future_result(|+r| + { result = Some(move r); }).unlinked().spawn { fail; } - assert future::get(&option::unwrap(result)) == Failure; + assert future::get(&option::unwrap(move result)) == Failure; } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -981,7 +986,7 @@ fn test_spawn_conversation() { let (recv_str, send_int) = do spawn_conversation |recv_int, send_str| { let input = comm::recv(recv_int); let output = int::str(input); - comm::send(send_str, output); + comm::send(send_str, move output); }; comm::send(send_int, 1); assert comm::recv(recv_str) == ~"1"; @@ -1134,7 +1139,7 @@ fn avoid_copying_the_body(spawnfn: fn(v: fn~())) { let x = ~1; let x_in_parent = ptr::addr_of(&(*x)) as uint; - do spawnfn { + do spawnfn |move x| { let x_in_child = ptr::addr_of(&(*x)) as uint; comm::send(ch, x_in_child); } @@ -1160,7 +1165,7 @@ fn test_avoid_copying_the_body_spawn_listener() { #[test] fn test_avoid_copying_the_body_task_spawn() { do avoid_copying_the_body |f| { - do task().spawn { + do task().spawn |move f| { f(); } } @@ -1178,7 +1183,7 @@ fn test_avoid_copying_the_body_spawn_listener_1() { #[test] fn test_avoid_copying_the_body_try() { do avoid_copying_the_body |f| { - do try { + do try |move f| { f() }; } @@ -1187,7 +1192,7 @@ fn test_avoid_copying_the_body_try() { #[test] fn test_avoid_copying_the_body_unlinked() { do avoid_copying_the_body |f| { - do spawn_unlinked { + do spawn_unlinked |move f| { f(); } } @@ -1212,7 +1217,7 @@ fn test_unkillable() { // We want to do this after failing do spawn_unlinked { - for iter::repeat(10u) { yield() } + for iter::repeat(10) { yield() } ch.send(()); } @@ -1226,12 +1231,12 @@ fn test_unkillable() { unsafe { do unkillable { let p = ~0; - let pp: *uint = cast::transmute(p); + let pp: *uint = cast::transmute(move p); // If we are killed here then the box will leak po.recv(); - let _p: ~int = cast::transmute(pp); + let _p: ~int = cast::transmute(move pp); } } @@ -1246,8 +1251,8 @@ fn test_unkillable_nested() { let (ch, po) = pipes::stream(); // We want to do this after failing - do spawn_unlinked { - for iter::repeat(10u) { yield() } + do spawn_unlinked |move ch| { + for iter::repeat(10) { yield() } ch.send(()); } @@ -1262,12 +1267,12 @@ fn test_unkillable_nested() { do unkillable { do unkillable {} // Here's the difference from the previous test. let p = ~0; - let pp: *uint = cast::transmute(p); + let pp: *uint = cast::transmute(move p); // If we are killed here then the box will leak po.recv(); - let _p: ~int = cast::transmute(pp); + let _p: ~int = cast::transmute(move pp); } } @@ -1311,7 +1316,7 @@ fn test_child_doesnt_ref_parent() { fn test_sched_thread_per_core() { let (chan, port) = pipes::stream(); - do spawn_sched(ThreadPerCore) { + do spawn_sched(ThreadPerCore) |move chan| { let cores = rt::rust_num_threads(); let reported_threads = rt::rust_sched_threads(); assert(cores as uint == reported_threads as uint); @@ -1325,7 +1330,7 @@ fn test_sched_thread_per_core() { fn test_spawn_thread_on_demand() { let (chan, port) = pipes::stream(); - do spawn_sched(ManualThreads(2)) { + do spawn_sched(ManualThreads(2)) |move chan| { let max_threads = rt::rust_sched_threads(); assert(max_threads as int == 2); let running_threads = rt::rust_sched_current_nonlazy_threads(); @@ -1333,7 +1338,7 @@ fn test_spawn_thread_on_demand() { let (chan2, port2) = pipes::stream(); - do spawn() { + do spawn() |move chan2| { chan2.send(()); } diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 6eaace1fa1a1..533e98514924 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -312,8 +312,8 @@ fn TCB(me: *rust_task, tasks: TaskGroupArc, ancestors: AncestorList, TCB { me: me, - tasks: tasks, - ancestors: ancestors, + tasks: move tasks, + ancestors: move ancestors, is_main: is_main, notifier: move notifier } @@ -330,7 +330,7 @@ struct AutoNotify { fn AutoNotify(chan: Chan) -> AutoNotify { AutoNotify { - notify_chan: chan, + notify_chan: move chan, failed: true // Un-set above when taskgroup successfully made. } } @@ -652,7 +652,7 @@ fn test_spawn_raw_unsupervise() { mut notify_chan: None, .. default_task_opts() }; - do spawn_raw(opts) { + do spawn_raw(move opts) { fail; } } @@ -667,7 +667,7 @@ fn test_spawn_raw_notify_success() { notify_chan: Some(move notify_ch), .. default_task_opts() }; - do spawn_raw(opts) |move task_ch| { + do spawn_raw(move opts) |move task_ch| { task_ch.send(get_task()); } let task_ = task_po.recv(); @@ -683,10 +683,10 @@ fn test_spawn_raw_notify_failure() { let opts = { linked: false, - notify_chan: Some(notify_ch), + notify_chan: Some(move notify_ch), .. default_task_opts() }; - do spawn_raw(opts) { + do spawn_raw(move opts) |move task_ch| { task_ch.send(get_task()); fail; } diff --git a/src/libcore/util.rs b/src/libcore/util.rs index 6c633f16abf2..8380cbf6b638 100644 --- a/src/libcore/util.rs +++ b/src/libcore/util.rs @@ -100,7 +100,7 @@ mod tests { let x = ~[(5, false)]; //FIXME #3387 assert x.eq(id(copy x)); let y = copy x; - assert x.eq(&id(y)); + assert x.eq(&id(move y)); } #[test] fn test_swap() { diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index b242ed5aee4f..2e91c4b22c43 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -340,15 +340,15 @@ pub fn splitn(v: &[T], n: uint, f: fn(t: &T) -> bool) -> ~[~[T]] { */ pub fn rsplit(v: &[T], f: fn(t: &T) -> bool) -> ~[~[T]] { let ln = len(v); - if (ln == 0u) { return ~[] } + if (ln == 0) { return ~[] } let mut end = ln; let mut result = ~[]; - while end > 0u { - match rposition_between(v, 0u, end, f) { + while end > 0 { + match rposition_between(v, 0, end, f) { None => break, Some(i) => { - result.push(slice(v, i + 1u, end)); + result.push(slice(v, i + 1, end)); end = i; } } @@ -416,7 +416,7 @@ pub fn shift(v: &mut ~[T]) -> T { pub fn unshift(v: &mut ~[T], x: T) { let mut vv = ~[move x]; *v <-> vv; - v.push_all_move(vv); + v.push_all_move(move vv); } pub fn consume(v: ~[T], f: fn(uint, v: T)) unsafe { @@ -433,7 +433,7 @@ pub fn consume(v: ~[T], f: fn(uint, v: T)) unsafe { } pub fn consume_mut(v: ~[mut T], f: fn(uint, v: T)) { - consume(vec::from_mut(v), f) + consume(vec::from_mut(move v), f) } /// Remove the last element from a vector and return it @@ -591,7 +591,7 @@ pub pure fn append_one(lhs: ~[T], x: T) -> ~[T] { #[inline(always)] pure fn append_mut(lhs: ~[mut T], rhs: &[const T]) -> ~[mut T] { - to_mut(append(from_mut(lhs), rhs)) + to_mut(append(from_mut(move lhs), rhs)) } /** @@ -1621,7 +1621,7 @@ impl ~[T]: MutableVector { } fn unshift(&mut self, x: T) { - unshift(self, x) + unshift(self, move x) } fn swap_remove(&mut self, index: uint) -> T { @@ -2208,7 +2208,7 @@ mod tests { #[test] fn test_dedup() { fn case(a: ~[uint], b: ~[uint]) { - let mut v = a; + let mut v = move a; v.dedup(); assert(v == b); } @@ -2464,13 +2464,13 @@ mod tests { let v1 = ~[1, 2, 3]; let v2 = ~[4, 5, 6]; - let z1 = zip(v1, v2); + let z1 = zip(move v1, move v2); assert ((1, 4) == z1[0]); assert ((2, 5) == z1[1]); assert ((3, 6) == z1[2]); - let (left, right) = unzip(z1); + let (left, right) = unzip(move z1); assert ((1, 4) == (left[0], right[0])); assert ((2, 5) == (left[1], right[1])); @@ -2768,7 +2768,7 @@ mod tests { unsafe { let x = ~[1, 2, 3]; let addr = raw::to_ptr(x); - let x_mut = to_mut(x); + let x_mut = to_mut(move x); let addr_mut = raw::to_ptr(x_mut); assert addr == addr_mut; } @@ -2779,7 +2779,7 @@ mod tests { unsafe { let x = ~[mut 1, 2, 3]; let addr = raw::to_ptr(x); - let x_imm = from_mut(x); + let x_imm = from_mut(move x); let addr_imm = raw::to_ptr(x_imm); assert addr == addr_imm; } @@ -2977,7 +2977,7 @@ mod tests { fn test_consume_fail() { let v = ~[(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do consume(v) |_i, _elt| { + do consume(move v) |_i, _elt| { if i == 2 { fail } @@ -2991,7 +2991,7 @@ mod tests { fn test_consume_mut_fail() { let v = ~[mut (~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do consume_mut(v) |_i, _elt| { + do consume_mut(move v) |_i, _elt| { if i == 2 { fail } @@ -3034,7 +3034,7 @@ mod tests { fn test_map_consume_fail() { let v = ~[(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do map_consume(v) |_elt| { + do map_consume(move v) |_elt| { if i == 2 { fail } From 90d06b80fdc7f07c5589ecd702da17998d0ef7ca Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:35:42 -0700 Subject: [PATCH 183/292] Make moves explicit in std tests --- src/libstd/arc.rs | 45 +++++++++++++------------- src/libstd/bitv.rs | 6 ++-- src/libstd/cell.rs | 2 +- src/libstd/comm.rs | 8 ++--- src/libstd/json.rs | 34 ++++++++++---------- src/libstd/net_ip.rs | 8 ++--- src/libstd/net_tcp.rs | 3 +- src/libstd/sort.rs | 2 +- src/libstd/sync.rs | 74 +++++++++++++++++++++---------------------- src/libstd/test.rs | 10 +++--- src/libstd/timer.rs | 2 +- 11 files changed, 98 insertions(+), 96 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 6178e64ff18c..9c793028a52d 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -124,7 +124,7 @@ pub fn mutex_arc_with_condvars(user_data: T, num_condvars: uint) -> MutexARC { let data = MutexARCInner { lock: mutex_with_condvars(num_condvars), - failed: false, data: user_data }; + failed: false, data: move user_data }; MutexARC { x: unsafe { shared_mutable_state(move data) } } } @@ -258,7 +258,7 @@ pub fn rw_arc_with_condvars(user_data: T, num_condvars: uint) -> RWARC { let data = RWARCInner { lock: rwlock_with_condvars(num_condvars), - failed: false, data: user_data }; + failed: false, data: move user_data }; RWARC { x: unsafe { shared_mutable_state(move data) }, cant_nest: () } } @@ -448,7 +448,7 @@ mod tests { let (c, p) = pipes::stream(); - do task::spawn() { + do task::spawn() |move c| { let p = pipes::PortSet(); c.send(p.chan()); @@ -471,8 +471,8 @@ mod tests { let arc = ~MutexARC(false); let arc2 = ~arc.clone(); let (c,p) = pipes::oneshot(); - let (c,p) = (~mut Some(c), ~mut Some(p)); - do task::spawn { + let (c,p) = (~mut Some(move c), ~mut Some(move p)); + do task::spawn |move arc2, move p| { // wait until parent gets in pipes::recv_one(option::swap_unwrap(p)); do arc2.access_cond |state, cond| { @@ -494,7 +494,7 @@ mod tests { let arc2 = ~arc.clone(); let (c,p) = pipes::stream(); - do task::spawn_unlinked { + do task::spawn_unlinked |move arc2, move p| { let _ = p.recv(); do arc2.access_cond |one, cond| { cond.signal(); @@ -513,7 +513,7 @@ mod tests { fn test_mutex_arc_poison() { let arc = ~MutexARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.access |one| { assert *one == 2; } @@ -527,21 +527,21 @@ mod tests { let arc = MutexARC(1); let arc2 = ~(&arc).clone(); let (c,p) = pipes::stream(); - do task::spawn { + do task::spawn |move c, move arc2| { do arc2.access |one| { c.send(()); assert *one == 2; } } let _ = p.recv(); - let one = unwrap_mutex_arc(arc); + let one = unwrap_mutex_arc(move arc); assert one == 1; } #[test] #[should_fail] #[ignore(cfg(windows))] fn test_rw_arc_poison_wr() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.write |one| { assert *one == 2; } @@ -554,7 +554,7 @@ mod tests { fn test_rw_arc_poison_ww() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.write |one| { assert *one == 2; } @@ -567,7 +567,7 @@ mod tests { fn test_rw_arc_poison_dw() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.write_downgrade |write_mode| { do (&write_mode).write |one| { assert *one == 2; @@ -582,7 +582,7 @@ mod tests { fn test_rw_arc_no_poison_rr() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.read |one| { assert *one == 2; } @@ -595,7 +595,7 @@ mod tests { fn test_rw_arc_no_poison_rw() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.read |one| { assert *one == 2; } @@ -608,9 +608,9 @@ mod tests { fn test_rw_arc_no_poison_dr() { let arc = ~RWARC(1); let arc2 = ~arc.clone(); - do task::try { + do task::try |move arc2| { do arc2.write_downgrade |write_mode| { - let read_mode = arc2.downgrade(write_mode); + let read_mode = arc2.downgrade(move write_mode); do (&read_mode).read |one| { assert *one == 2; } @@ -626,7 +626,7 @@ mod tests { let arc2 = ~arc.clone(); let (c,p) = pipes::stream(); - do task::spawn { + do task::spawn |move arc2, move c| { do arc2.write |num| { for 10.times { let tmp = *num; @@ -642,7 +642,8 @@ mod tests { let mut children = ~[]; for 5.times { let arc3 = ~arc.clone(); - do task::task().future_result(|+r| children.push(r)).spawn { + do task::task().future_result(|+r| children.push(move r)).spawn + |move arc3| { do arc3.read |num| { assert *num >= 0; } @@ -670,9 +671,9 @@ mod tests { let mut reader_convos = ~[]; for 10.times { let ((rc1,rp1),(rc2,rp2)) = (pipes::stream(),pipes::stream()); - reader_convos.push((rc1,rp2)); + reader_convos.push((move rc1, move rp2)); let arcn = ~arc.clone(); - do task::spawn { + do task::spawn |move rp1, move rc2, move arcn| { rp1.recv(); // wait for downgrader to give go-ahead do arcn.read |state| { assert *state == 31337; @@ -684,7 +685,7 @@ mod tests { // Writer task let arc2 = ~arc.clone(); let ((wc1,wp1),(wc2,wp2)) = (pipes::stream(),pipes::stream()); - do task::spawn { + do task::spawn |move arc2, move wc2, move wp1| { wp1.recv(); do arc2.write_cond |state, cond| { assert *state == 0; @@ -717,7 +718,7 @@ mod tests { } } } - let read_mode = arc.downgrade(write_mode); + let read_mode = arc.downgrade(move write_mode); do (&read_mode).read |state| { // complete handshake with other readers for vec::each(reader_convos) |x| { diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 91af4a3d6531..2b8e9b6bbd96 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -96,7 +96,7 @@ struct BigBitv { } fn BigBitv(storage: ~[mut uint]) -> BigBitv { - BigBitv {storage: storage} + BigBitv {storage: move storage} } /** @@ -223,7 +223,7 @@ pub fn Bitv (nbits: uint, init: bool) -> Bitv { let s = to_mut(from_elem(nelems, elem)); Big(~BigBitv(move s)) }; - Bitv {rep: rep, nbits: nbits} + Bitv {rep: move rep, nbits: nbits} } priv impl Bitv { @@ -301,7 +301,7 @@ impl Bitv { let st = to_mut(from_elem(self.nbits / uint_bits + 1, 0)); let len = st.len(); for uint::range(0, len) |i| { st[i] = b.storage[i]; }; - Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: st})} + Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: move st})} } } } diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index c888957728a3..4f79bf2b3169 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -57,7 +57,7 @@ fn test_basic() { let value = value_cell.take(); assert value == ~10; assert value_cell.is_empty(); - value_cell.put_back(value); + value_cell.put_back(move value); assert !value_cell.is_empty(); } diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index 1a897a2c2fa9..e604b87b2afd 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -52,12 +52,12 @@ pub fn DuplexStream() let (c2, p1) = pipes::stream(); let (c1, p2) = pipes::stream(); (DuplexStream { - chan: c1, - port: p1 + chan: move c1, + port: move p1 }, DuplexStream { - chan: c2, - port: p2 + chan: move c2, + port: move p2 }) } diff --git a/src/libstd/json.rs b/src/libstd/json.rs index bb331240b765..0d3391c1867c 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -329,8 +329,8 @@ pub fn Parser(rdr: io::Reader) -> Parser { Parser { rdr: rdr, ch: rdr.read_char(), - line: 1u, - col: 1u, + line: 1, + col: 1, } } @@ -342,7 +342,7 @@ pub impl Parser { self.parse_whitespace(); // Make sure there is no trailing characters. if self.eof() { - Ok(value) + Ok(move value) } else { self.error(~"trailing characters") } @@ -610,12 +610,12 @@ priv impl Parser { if self.ch == ']' { self.bump(); - return Ok(List(values)); + return Ok(List(move values)); } loop { match move self.parse_value() { - Ok(move v) => values.push(v), + Ok(move v) => values.push(move v), Err(move e) => return Err(e) } @@ -626,7 +626,7 @@ priv impl Parser { match self.ch { ',' => self.bump(), - ']' => { self.bump(); return Ok(List(values)); } + ']' => { self.bump(); return Ok(List(move values)); } _ => return self.error(~"expected `,` or `]`") } }; @@ -640,7 +640,7 @@ priv impl Parser { if self.ch == '}' { self.bump(); - return Ok(Object(values)); + return Ok(Object(move values)); } while !self.eof() { @@ -664,14 +664,14 @@ priv impl Parser { self.bump(); match move self.parse_value() { - Ok(move value) => { values.insert(key, value); } + Ok(move value) => { values.insert(key, move value); } Err(move e) => return Err(e) } self.parse_whitespace(); match self.ch { ',' => self.bump(), - '}' => { self.bump(); return Ok(Object(values)); } + '}' => { self.bump(); return Ok(Object(move values)); } _ => { if self.eof() { break; } return self.error(~"expected `,` or `}`"); @@ -703,7 +703,7 @@ pub struct Deserializer { pub fn Deserializer(rdr: io::Reader) -> Result { match move from_reader(rdr) { Ok(move json) => { - let des = Deserializer { json: json, stack: ~[] }; + let des = Deserializer { json: move json, stack: ~[] }; Ok(move des) } Err(move e) => Err(e) @@ -819,7 +819,7 @@ pub impl Deserializer: serialization::Deserializer { }; let res = f(len); self.pop(); - res + move res } fn read_managed_vec(&self, f: fn(uint) -> T) -> T { @@ -830,7 +830,7 @@ pub impl Deserializer: serialization::Deserializer { }; let res = f(len); self.pop(); - res + move res } fn read_vec_elt(&self, idx: uint, f: fn() -> T) -> T { @@ -851,14 +851,14 @@ pub impl Deserializer: serialization::Deserializer { debug!("read_rec()"); let value = f(); self.pop(); - value + move value } fn read_struct(&self, _name: &str, f: fn() -> T) -> T { debug!("read_struct()"); let value = f(); self.pop(); - value + move value } fn read_field(&self, name: &str, idx: uint, f: fn() -> T) -> T { @@ -891,7 +891,7 @@ pub impl Deserializer: serialization::Deserializer { debug!("read_tup(len=%u)", len); let value = f(); self.pop(); - value + move value } fn read_tup_elt(&self, idx: uint, f: fn() -> T) -> T { @@ -1183,11 +1183,11 @@ mod tests { for items.each |item| { match *item { - (copy key, copy value) => { d.insert(key, value); }, + (copy key, copy value) => { d.insert(key, move value); }, } }; - Object(d) + Object(move d) } #[test] diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 2d9dd5bdf4e8..cf5323c498b7 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -128,7 +128,7 @@ pub mod v4 { */ pub fn parse_addr(ip: &str) -> IpAddr { match try_parse_addr(ip) { - result::Ok(copy addr) => addr, + result::Ok(move addr) => move addr, result::Err(ref err_data) => fail err_data.err_msg } } @@ -214,7 +214,7 @@ pub mod v6 { */ pub fn parse_addr(ip: &str) -> IpAddr { match try_parse_addr(ip) { - result::Ok(copy addr) => addr, + result::Ok(move addr) => move addr, result::Err(copy err_data) => fail err_data.err_msg } } @@ -353,7 +353,7 @@ mod test { } // note really sure how to realiably test/assert // this.. mostly just wanting to see it work, atm. - let results = result::unwrap(ga_result); + let results = result::unwrap(move ga_result); log(debug, fmt!("test_get_addr: Number of results for %s: %?", localhost_name, vec::len(results))); for vec::each(results) |r| { @@ -366,7 +366,7 @@ mod test { } // at least one result.. this is going to vary from system // to system, based on stuff like the contents of /etc/hosts - assert vec::len(results) > 0; + assert !results.is_empty(); } #[test] #[ignore(reason = "valgrind says it's leaky")] diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 87dea021f5b7..db5c1328e62b 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -562,7 +562,8 @@ pub fn listen(host_ip: ip::IpAddr, port: uint, backlog: uint, new_connect_cb: fn~(TcpNewConnection, comm::Chan>)) -> result::Result<(), TcpListenErrData> unsafe { - do listen_common(move host_ip, port, backlog, iotask, on_establish_cb) + do listen_common(move host_ip, port, backlog, iotask, + move on_establish_cb) // on_connect_cb |move new_connect_cb, handle| unsafe { let server_data_ptr = uv::ll::get_data_for_uv_handle(handle) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index f783addcf508..0b00da9f81d7 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -250,7 +250,7 @@ mod test_qsort { sort::quick_sort(|x, y| { int::le(*x, *y) }, names); - let immut_names = vec::from_mut(names); + let immut_names = vec::from_mut(move names); let pairs = vec::zip(expected, immut_names); for vec::each(pairs) |p| { diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index dd1dab835876..73fc78a091a4 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -25,7 +25,7 @@ struct Waitqueue { head: pipes::Port, fn new_waitqueue() -> Waitqueue { let (block_tail, block_head) = pipes::stream(); - Waitqueue { head: block_head, tail: block_tail } + Waitqueue { head: move block_head, tail: move block_tail } } // Signals one live task from the queue. @@ -71,7 +71,7 @@ enum Sem = Exclusive>; #[doc(hidden)] fn new_sem(count: int, q: Q) -> Sem { Sem(exclusive(SemInner { - mut count: count, waiters: new_waitqueue(), blocked: q })) + mut count: count, waiters: new_waitqueue(), blocked: move q })) } #[doc(hidden)] fn new_sem_and_signal(count: int, num_condvars: uint) @@ -686,7 +686,7 @@ mod tests { fn test_sem_as_mutex() { let s = ~semaphore(1); let s2 = ~s.clone(); - do task::spawn { + do task::spawn |move s2| { do s2.access { for 5.times { task::yield(); } } @@ -701,7 +701,7 @@ mod tests { let (c,p) = pipes::stream(); let s = ~semaphore(0); let s2 = ~s.clone(); - do task::spawn { + do task::spawn |move s2, move c| { s2.acquire(); c.send(()); } @@ -713,7 +713,7 @@ mod tests { let (c,p) = pipes::stream(); let s = ~semaphore(0); let s2 = ~s.clone(); - do task::spawn { + do task::spawn |move s2, move p| { for 5.times { task::yield(); } s2.release(); let _ = p.recv(); @@ -729,7 +729,7 @@ mod tests { let s2 = ~s.clone(); let (c1,p1) = pipes::stream(); let (c2,p2) = pipes::stream(); - do task::spawn { + do task::spawn |move s2, move c1, move p2| { do s2.access { let _ = p2.recv(); c1.send(()); @@ -748,10 +748,10 @@ mod tests { let s = ~semaphore(1); let s2 = ~s.clone(); let (c,p) = pipes::stream(); - let child_data = ~mut Some((s2,c)); + let child_data = ~mut Some((move s2, move c)); do s.access { let (s2,c) = option::swap_unwrap(child_data); - do task::spawn { + do task::spawn |move c, move s2| { c.send(()); do s2.access { } c.send(()); @@ -774,7 +774,7 @@ mod tests { let m2 = ~m.clone(); let mut sharedstate = ~0; let ptr = ptr::addr_of(&(*sharedstate)); - do task::spawn { + do task::spawn |move m2, move c| { let sharedstate: &mut int = unsafe { cast::reinterpret_cast(&ptr) }; access_shared(sharedstate, m2, 10); @@ -803,7 +803,7 @@ mod tests { // Child wakes up parent do m.lock_cond |cond| { let m2 = ~m.clone(); - do task::spawn { + do task::spawn |move m2| { do m2.lock_cond |cond| { let woken = cond.signal(); assert woken; @@ -814,7 +814,7 @@ mod tests { // Parent wakes up child let (chan,port) = pipes::stream(); let m3 = ~m.clone(); - do task::spawn { + do task::spawn |move chan, move m3| { do m3.lock_cond |cond| { chan.send(()); cond.wait(); @@ -836,8 +836,8 @@ mod tests { for num_waiters.times { let mi = ~m.clone(); let (chan, port) = pipes::stream(); - ports.push(port); - do task::spawn { + ports.push(move port); + do task::spawn |move chan, move mi| { do mi.lock_cond |cond| { chan.send(()); cond.wait(); @@ -867,7 +867,7 @@ mod tests { fn test_mutex_cond_no_waiter() { let m = ~Mutex(); let m2 = ~m.clone(); - do task::try { + do task::try |move m| { do m.lock_cond |_x| { } }; do m2.lock_cond |cond| { @@ -880,7 +880,7 @@ mod tests { let m = ~Mutex(); let m2 = ~m.clone(); - let result: result::Result<(),()> = do task::try { + let result: result::Result<(),()> = do task::try |move m2| { do m2.lock { fail; } @@ -896,9 +896,9 @@ mod tests { let m = ~Mutex(); let m2 = ~m.clone(); - let result: result::Result<(),()> = do task::try { + let result: result::Result<(),()> = do task::try |move m2| { let (c,p) = pipes::stream(); - do task::spawn { // linked + do task::spawn |move p| { // linked let _ = p.recv(); // wait for sibling to get in the mutex task::yield(); fail; @@ -921,19 +921,19 @@ mod tests { let m2 = ~m.clone(); let (c,p) = pipes::stream(); - let result: result::Result<(),()> = do task::try { + let result: result::Result<(),()> = do task::try |move c, move m2| { let mut sibling_convos = ~[]; for 2.times { let (c,p) = pipes::stream(); - let c = ~mut Some(c); - sibling_convos.push(p); + let c = ~mut Some(move c); + sibling_convos.push(move p); let mi = ~m2.clone(); // spawn sibling task - do task::spawn { // linked + do task::spawn |move mi, move c| { // linked do mi.lock_cond |cond| { let c = option::swap_unwrap(c); c.send(()); // tell sibling to go ahead - let _z = SendOnFailure(c); + let _z = SendOnFailure(move c); cond.wait(); // block forever } } @@ -942,7 +942,7 @@ mod tests { let _ = p.recv(); // wait for sibling to get in the mutex } do m2.lock { } - c.send(sibling_convos); // let parent wait on all children + c.send(move sibling_convos); // let parent wait on all children fail; }; assert result.is_err(); @@ -959,7 +959,7 @@ mod tests { fn SendOnFailure(c: pipes::Chan<()>) -> SendOnFailure { SendOnFailure { - c: c + c: move c } } } @@ -969,7 +969,7 @@ mod tests { let m = ~Mutex(); do m.lock_cond |cond| { let m2 = ~m.clone(); - do task::spawn { + do task::spawn |move m2| { do m2.lock_cond |cond| { cond.signal_on(0); } @@ -983,7 +983,7 @@ mod tests { let m = ~mutex_with_condvars(2); let m2 = ~m.clone(); let (c,p) = pipes::stream(); - do task::spawn { + do task::spawn |move m2, move c| { do m2.lock_cond |cond| { c.send(()); cond.wait_on(1); @@ -1032,7 +1032,7 @@ mod tests { }, DowngradeRead => do x.write_downgrade |mode| { - let mode = x.downgrade(mode); + let mode = x.downgrade(move mode); (&mode).read(blk); }, } @@ -1046,7 +1046,7 @@ mod tests { let x2 = ~x.clone(); let mut sharedstate = ~0; let ptr = ptr::addr_of(&(*sharedstate)); - do task::spawn { + do task::spawn |move c, move x2| { let sharedstate: &mut int = unsafe { cast::reinterpret_cast(&ptr) }; access_shared(sharedstate, x2, mode1, 10); @@ -1089,7 +1089,7 @@ mod tests { let x2 = ~x.clone(); let (c1,p1) = pipes::stream(); let (c2,p2) = pipes::stream(); - do task::spawn { + do task::spawn |move c1, move x2, move p2| { if !make_mode2_go_first { let _ = p2.recv(); // parent sends to us once it locks, or ... } @@ -1126,10 +1126,10 @@ mod tests { // Tests that downgrade can unlock the lock in both modes let x = ~RWlock(); do lock_rwlock_in_mode(x, Downgrade) { } - test_rwlock_handshake(x, Read, Read, false); + test_rwlock_handshake(move x, Read, Read, false); let y = ~RWlock(); do lock_rwlock_in_mode(y, DowngradeRead) { } - test_rwlock_exclusion(y, Write, Write); + test_rwlock_exclusion(move y, Write, Write); } #[test] fn test_rwlock_read_recursive() { @@ -1144,7 +1144,7 @@ mod tests { // Child wakes up parent do x.write_cond |cond| { let x2 = ~x.clone(); - do task::spawn { + do task::spawn |move x2| { do x2.write_cond |cond| { let woken = cond.signal(); assert woken; @@ -1155,7 +1155,7 @@ mod tests { // Parent wakes up child let (chan,port) = pipes::stream(); let x3 = ~x.clone(); - do task::spawn { + do task::spawn |move x3, move chan| { do x3.write_cond |cond| { chan.send(()); cond.wait(); @@ -1190,8 +1190,8 @@ mod tests { for num_waiters.times { let xi = ~x.clone(); let (chan, port) = pipes::stream(); - ports.push(port); - do task::spawn { + ports.push(move port); + do task::spawn |move chan, move xi| { do lock_cond(xi, dg1) |cond| { chan.send(()); cond.wait(); @@ -1226,7 +1226,7 @@ mod tests { let x = ~RWlock(); let x2 = ~x.clone(); - let result: result::Result<(),()> = do task::try { + let result: result::Result<(),()> = do task::try |move x2| { do lock_rwlock_in_mode(x2, mode1) { fail; } @@ -1264,7 +1264,7 @@ mod tests { let x = ~RWlock(); let y = ~RWlock(); do x.write_downgrade |xwrite| { - let mut xopt = Some(xwrite); + let mut xopt = Some(move xwrite); do y.write_downgrade |_ywrite| { y.downgrade(option::swap_unwrap(&mut xopt)); error!("oops, y.downgrade(x) should have failed!"); diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 162a5ecc5fcf..ca83dbf17ed1 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -130,7 +130,7 @@ pub fn run_tests_console(opts: &TestOpts, st.failed += 1u; write_failed(st.out, st.use_color); st.out.write_line(~""); - st.failures.push(test); + st.failures.push(move test); } TrIgnored => { st.ignored += 1u; @@ -249,7 +249,7 @@ fn should_sort_failures_before_printing_them() { mut passed: 0u, mut failed: 0u, mut ignored: 0u, - mut failures: ~[test_b, test_a]}; + mut failures: ~[move test_b, move test_a]}; print_failures(st); }; @@ -534,9 +534,9 @@ mod tests { for vec::each(names) |name| { let test = {name: *name, testfn: copy testfn, ignore: false, should_fail: false}; - tests.push(test); + tests.push(move test); } - tests + move tests }; let filtered = filter_tests(&opts, tests); @@ -549,7 +549,7 @@ mod tests { ~"test::parse_ignored_flag", ~"test::sort_tests"]; - let pairs = vec::zip(expected, filtered); + let pairs = vec::zip(expected, move filtered); for vec::each(pairs) |p| { match *p { diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index cc62e32608bc..199fba459144 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -55,7 +55,7 @@ pub fn delayed_send(iotask: IoTask, // delayed_send_cb has been processed by libuv core::comm::recv(timer_done_po); // notify the caller immediately - core::comm::send(ch, copy(val)); + core::comm::send(ch, move(val)); // uv_close for this timer has been processed core::comm::recv(timer_done_po); }; From d52f988dbb8c147d310926434b7ed2415a4a8719 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:43:54 -0700 Subject: [PATCH 184/292] Make moves explicit in rustdoc --- src/rustdoc/astsrv.rs | 6 +++--- src/rustdoc/attr_pass.rs | 2 +- src/rustdoc/fold.rs | 24 ++++++++++++------------ src/rustdoc/markdown_pass.rs | 19 ++++++++++--------- src/rustdoc/markdown_writer.rs | 15 ++++++++------- src/rustdoc/page_pass.rs | 2 +- src/rustdoc/rustdoc.rs | 2 +- src/rustdoc/sort_pass.rs | 2 +- src/rustdoc/text_pass.rs | 2 +- 9 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/rustdoc/astsrv.rs b/src/rustdoc/astsrv.rs index 2e6cbf579c8e..27d4d51a010f 100644 --- a/src/rustdoc/astsrv.rs +++ b/src/rustdoc/astsrv.rs @@ -57,14 +57,14 @@ fn from_file(file: ~str, owner: SrvOwner) -> T { fn run(owner: SrvOwner, source: ~str, +parse: Parser) -> T { let srv_ = Srv({ - ch: do task::spawn_listener |po| { + ch: do task::spawn_listener |move parse, po| { act(po, source, parse); } }); let res = owner(srv_); comm::send(srv_.ch, Exit); - return res; + move res } fn act(po: comm::Port, source: ~str, parse: Parser) { @@ -97,7 +97,7 @@ fn exec( let msg = HandleRequest(fn~(move f, ctxt: Ctxt) { comm::send(ch, f(ctxt)) }); - comm::send(srv.ch, msg); + comm::send(srv.ch, move msg); comm::recv(po) } diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs index 56ebbfe9b51f..cd310791b4df 100644 --- a/src/rustdoc/attr_pass.rs +++ b/src/rustdoc/attr_pass.rs @@ -93,7 +93,7 @@ fn parse_item_attrs( srv: astsrv::Srv, id: doc::AstId, +parse_attrs: fn~(~[ast::attribute]) -> T) -> T { - do astsrv::exec(srv) |ctxt| { + do astsrv::exec(srv) |move parse_attrs, ctxt| { let attrs = match ctxt.ast_map.get(id) { ast_map::node_item(item, _) => item.attrs, ast_map::node_foreign_item(item, _, _) => item.attrs, diff --git a/src/rustdoc/fold.rs b/src/rustdoc/fold.rs index 28dbdaeea801..e8d914bd2cb8 100644 --- a/src/rustdoc/fold.rs +++ b/src/rustdoc/fold.rs @@ -71,18 +71,18 @@ fn mk_fold( ) -> Fold { Fold({ ctxt: ctxt, - fold_doc: fold_doc, - fold_crate: fold_crate, - fold_item: fold_item, - fold_mod: fold_mod, - fold_nmod: fold_nmod, - fold_fn: fold_fn, - fold_const: fold_const, - fold_enum: fold_enum, - fold_trait: fold_trait, - fold_impl: fold_impl, - fold_type: fold_type, - fold_struct: fold_struct, + fold_doc: move fold_doc, + fold_crate: move fold_crate, + fold_item: move fold_item, + fold_mod: move fold_mod, + fold_nmod: move fold_nmod, + fold_fn: move fold_fn, + fold_const: move fold_const, + fold_enum: move fold_enum, + fold_trait: move fold_trait, + fold_impl: move fold_impl, + fold_type: move fold_type, + fold_struct: move fold_struct }) } diff --git a/src/rustdoc/markdown_pass.rs b/src/rustdoc/markdown_pass.rs index 66c465b60215..99357e254a47 100644 --- a/src/rustdoc/markdown_pass.rs +++ b/src/rustdoc/markdown_pass.rs @@ -9,13 +9,14 @@ export mk_pass; export header_kind, header_name, header_text; fn mk_pass(+writer_factory: WriterFactory) -> Pass { - let f = fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { + let f = fn~(move writer_factory, + srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { run(srv, doc, copy writer_factory) }; { name: ~"markdown", - f: f + f: move f } } @@ -44,7 +45,7 @@ fn run( ~"mods last", mods_last ).f(srv, doc); - write_markdown(sorted_doc, writer_factory); + write_markdown(sorted_doc, move writer_factory); return doc; } @@ -118,9 +119,9 @@ fn should_request_new_writer_for_each_page() { let (srv, doc) = test::create_doc_srv(~"mod a { }"); // Split the document up into pages let doc = page_pass::mk_pass(config::DocPerMod).f(srv, doc); - write_markdown(doc, writer_factory); + write_markdown(doc, move writer_factory); // We expect two pages to have been written - for iter::repeat(2u) { + for iter::repeat(2) { comm::recv(po); } } @@ -150,8 +151,8 @@ fn should_write_title_for_each_page() { let (srv, doc) = test::create_doc_srv( ~"#[link(name = \"core\")]; mod a { }"); let doc = page_pass::mk_pass(config::DocPerMod).f(srv, doc); - write_markdown(doc, writer_factory); - for iter::repeat(2u) { + write_markdown(doc, move writer_factory); + for iter::repeat(2) { let (page, markdown) = comm::recv(po); match page { doc::CratePage(_) => { @@ -845,7 +846,7 @@ mod test { doc: doc::Doc ) -> ~str { let (writer_factory, po) = markdown_writer::future_writer_factory(); - write_markdown(doc, writer_factory); + write_markdown(doc, move writer_factory); return comm::recv(po).second(); } @@ -854,7 +855,7 @@ mod test { doc: doc::Doc ) -> ~str { let (writer_factory, po) = markdown_writer::future_writer_factory(); - let pass = mk_pass(writer_factory); + let pass = mk_pass(move writer_factory); pass.f(srv, doc); return comm::recv(po).second(); } diff --git a/src/rustdoc/markdown_writer.rs b/src/rustdoc/markdown_writer.rs index f505f9d0b993..ea559ae2ee6b 100644 --- a/src/rustdoc/markdown_writer.rs +++ b/src/rustdoc/markdown_writer.rs @@ -146,7 +146,8 @@ fn readclose(fd: libc::c_int) -> ~str { } fn generic_writer(+process: fn~(markdown: ~str)) -> Writer { - let ch = do task::spawn_listener |po: comm::Port| { + let ch = do task::spawn_listener + |move process, po: comm::Port| { let mut markdown = ~""; let mut keep_going = true; while keep_going { @@ -155,7 +156,7 @@ fn generic_writer(+process: fn~(markdown: ~str)) -> Writer { Done => keep_going = false } } - process(markdown); + process(move markdown); }; fn~(+instr: WriteInstr) { @@ -274,22 +275,22 @@ fn future_writer_factory( let writer_ch = comm::Chan(&writer_po); do task::spawn { let (writer, future) = future_writer(); - comm::send(writer_ch, writer); + comm::send(writer_ch, move writer); let s = future::get(&future); comm::send(markdown_ch, (page, s)); } comm::recv(writer_po) }; - (writer_factory, markdown_po) + (move writer_factory, markdown_po) } fn future_writer() -> (Writer, future::Future<~str>) { let (chan, port) = pipes::stream(); - let writer = fn~(+instr: WriteInstr) { + let writer = fn~(move chan, +instr: WriteInstr) { chan.send(copy instr); }; - let future = do future::from_fn { + let future = do future::from_fn |move port| { let mut res = ~""; loop { match port.recv() { @@ -299,5 +300,5 @@ fn future_writer() -> (Writer, future::Future<~str>) { } res }; - (writer, future) + (move writer, move future) } diff --git a/src/rustdoc/page_pass.rs b/src/rustdoc/page_pass.rs index ad3f679a97cb..fc911d23e043 100644 --- a/src/rustdoc/page_pass.rs +++ b/src/rustdoc/page_pass.rs @@ -46,7 +46,7 @@ fn make_doc_from_pages(page_port: PagePort) -> doc::Doc { loop { let val = comm::recv(page_port); if val.is_some() { - pages += ~[option::unwrap(val)]; + pages += ~[option::unwrap(move val)]; } else { break; } diff --git a/src/rustdoc/rustdoc.rs b/src/rustdoc/rustdoc.rs index b79b6ba21899..e09f57339a7c 100755 --- a/src/rustdoc/rustdoc.rs +++ b/src/rustdoc/rustdoc.rs @@ -87,5 +87,5 @@ fn time(what: ~str, f: fn() -> T) -> T { let rv = f(); let end = std::time::precise_time_s(); info!("time: %3.3f s %s", end - start, what); - return rv; + move rv } diff --git a/src/rustdoc/sort_pass.rs b/src/rustdoc/sort_pass.rs index 497c076d3ab6..0f0ee1a10663 100644 --- a/src/rustdoc/sort_pass.rs +++ b/src/rustdoc/sort_pass.rs @@ -10,7 +10,7 @@ type ItemLtEq = pure fn~(v1: &doc::ItemTag, v2: &doc::ItemTag) -> bool; fn mk_pass(name: ~str, +lteq: ItemLtEq) -> Pass { { name: name, - f: fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { + f: fn~(move lteq, srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { run(srv, doc, lteq) } } diff --git a/src/rustdoc/text_pass.rs b/src/rustdoc/text_pass.rs index b929cd0aa91a..f5ba9e9a2c9a 100644 --- a/src/rustdoc/text_pass.rs +++ b/src/rustdoc/text_pass.rs @@ -7,7 +7,7 @@ export mk_pass; fn mk_pass(name: ~str, +op: fn~(~str) -> ~str) -> Pass { { name: name, - f: fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { + f: fn~(move op, srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { run(srv, doc, op) } } From e18c6bb3b6f9daab455227dae384d9a3b961aa1c Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:44:15 -0700 Subject: [PATCH 185/292] Make moves explicit in aux test files --- src/test/auxiliary/cci_class_6.rs | 2 +- src/test/auxiliary/test_comm.rs | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/auxiliary/cci_class_6.rs b/src/test/auxiliary/cci_class_6.rs index 6cf86aff055e..da1a8b5f0ed8 100644 --- a/src/test/auxiliary/cci_class_6.rs +++ b/src/test/auxiliary/cci_class_6.rs @@ -21,7 +21,7 @@ fn cat(in_x : uint, in_y : int, -in_info: ~[U]) -> cat { cat { meows: in_x, how_hungry: in_y, - info: in_info + info: move in_info } } diff --git a/src/test/auxiliary/test_comm.rs b/src/test/auxiliary/test_comm.rs index 77f107fda090..18960d0ad8aa 100644 --- a/src/test/auxiliary/test_comm.rs +++ b/src/test/auxiliary/test_comm.rs @@ -7,7 +7,6 @@ use libc::size_t; -export port::{}; export port; export recv; @@ -65,13 +64,13 @@ fn recv(p: port) -> T { recv_((**p).po) } /// Receive on a raw port pointer fn recv_(p: *rust_port) -> T { - let yield = 0u; + let yield = 0; let yieldp = ptr::addr_of(&yield); let mut res; res = rusti::init::(); rustrt::port_recv(ptr::addr_of(&res) as *uint, p, yieldp); - if yield != 0u { + if yield != 0 { // Data isn't available yet, so res has not been initialized. task::yield(); } else { @@ -79,7 +78,7 @@ fn recv_(p: *rust_port) -> T { // this is a good place to yield task::yield(); } - return res; + move res } From f5f3a75b6501c987ffb34b3fb7510e0139c64bb8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:44:34 -0700 Subject: [PATCH 186/292] Make moves explicit in bench tests --- src/test/bench/graph500-bfs.rs | 22 ++++++------ src/test/bench/msgsend-pipes-shared.rs | 14 ++++---- src/test/bench/msgsend-pipes.rs | 16 ++++----- src/test/bench/msgsend-ring-mutex-arcs.rs | 24 ++++++------- src/test/bench/msgsend-ring-pipes.rs | 28 +++++++-------- src/test/bench/msgsend-ring-rw-arcs.rs | 24 ++++++------- src/test/bench/msgsend-ring.rs | 2 +- src/test/bench/msgsend.rs | 8 ++--- src/test/bench/pingpong.rs | 36 +++++++++---------- src/test/bench/shootout-k-nucleotide-pipes.rs | 14 ++++---- src/test/bench/shootout-pfib.rs | 10 +++--- src/test/bench/task-perf-alloc-unwind.rs | 5 +-- .../bench/task-perf-jargon-metal-smoke.rs | 10 +++--- src/test/bench/task-perf-linked-failure.rs | 4 +-- .../bench/task-perf-word-count-generic.rs | 30 ++++++++-------- 15 files changed, 124 insertions(+), 123 deletions(-) diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index 5acde71c6fd6..c877d1d36577 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -119,7 +119,7 @@ fn bfs(graph: graph, key: node_id) -> bfs_result { Q.add_back(key); marks[key] = key; - while Q.size() > 0u { + while Q.size() > 0 { let t = Q.pop_front(); do graph[t].each() |k| { @@ -131,7 +131,7 @@ fn bfs(graph: graph, key: node_id) -> bfs_result { }; } - vec::from_mut(marks) + vec::from_mut(move marks) } /** @@ -167,11 +167,11 @@ fn bfs2(graph: graph, key: node_id) -> bfs_result { } } - let mut i = 0u; + let mut i = 0; while vec::any(colors, is_gray) { // Do the BFS. log(info, fmt!("PBFS iteration %?", i)); - i += 1u; + i += 1; colors = do colors.mapi() |i, c| { let c : color = *c; match c { @@ -245,13 +245,13 @@ fn pbfs(&&graph: arc::ARC, key: node_id) -> bfs_result { i += 1; let old_len = colors.len(); - let color = arc::ARC(colors); + let color = arc::ARC(move colors); let color_vec = arc::get(&color); // FIXME #3387 requires this temp colors = do par::mapi_factory(*color_vec) { let colors = arc::clone(&color); let graph = arc::clone(&graph); - fn~(+i: uint, +c: color) -> color { + fn~(move graph, move colors, +i: uint, +c: color) -> color { let c : color = c; let colors = arc::get(&colors); let graph = arc::get(&graph); @@ -388,7 +388,7 @@ fn main() { let args = os::args(); let args = if os::getenv(~"RUST_BENCH").is_some() { ~[~"", ~"15", ~"48"] - } else if args.len() <= 1u { + } else if args.len() <= 1 { ~[~"", ~"10", ~"16"] } else { args @@ -400,21 +400,21 @@ fn main() { let do_sequential = true; let start = time::precise_time_s(); - let edges = make_edges(scale, 16u); + let edges = make_edges(scale, 16); let stop = time::precise_time_s(); io::stdout().write_line(fmt!("Generated %? edges in %? seconds.", vec::len(edges), stop - start)); let start = time::precise_time_s(); - let graph = make_graph(1u << scale, edges); + let graph = make_graph(1 << scale, edges); let stop = time::precise_time_s(); - let mut total_edges = 0u; + let mut total_edges = 0; vec::each(graph, |edges| { total_edges += edges.len(); true }); io::stdout().write_line(fmt!("Generated graph with %? edges in %? seconds.", - total_edges / 2u, + total_edges / 2, stop - start)); let mut total_seq = 0.0; diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index d60937af13c8..88ca0d3e0c2d 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -19,7 +19,7 @@ use io::WriterUtil; use pipes::{Port, Chan, SharedChan}; macro_rules! move_out ( - { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); y } } + { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } } ) enum request { @@ -50,26 +50,26 @@ fn run(args: &[~str]) { let (to_parent, from_child) = pipes::stream(); let (to_child, from_parent) = pipes::stream(); - let to_child = SharedChan(to_child); + let to_child = SharedChan(move to_child); let size = uint::from_str(args[1]).get(); let workers = uint::from_str(args[2]).get(); let num_bytes = 100; let start = std::time::precise_time_s(); let mut worker_results = ~[]; - for uint::range(0u, workers) |i| { + for uint::range(0, workers) |_i| { let to_child = to_child.clone(); do task::task().future_result(|+r| { - worker_results.push(r); - }).spawn { - for uint::range(0u, size / workers) |_i| { + worker_results.push(move r); + }).spawn |move to_child| { + for uint::range(0, size / workers) |_i| { //error!("worker %?: sending %? bytes", i, num_bytes); to_child.send(bytes(num_bytes)); } //error!("worker %? exiting", i); }; } - do task::spawn { + do task::spawn |move from_parent, move to_parent| { server(from_parent, to_parent); } diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index e2d115600eff..ce3fd5134ac5 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -15,7 +15,7 @@ use io::WriterUtil; use pipes::{Port, PortSet, Chan}; macro_rules! move_out ( - { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); y } } + { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } } ) enum request { @@ -46,27 +46,27 @@ fn run(args: &[~str]) { let (to_parent, from_child) = pipes::stream(); let (to_child, from_parent_) = pipes::stream(); let from_parent = PortSet(); - from_parent.add(from_parent_); + from_parent.add(move from_parent_); let size = uint::from_str(args[1]).get(); let workers = uint::from_str(args[2]).get(); let num_bytes = 100; let start = std::time::precise_time_s(); let mut worker_results = ~[]; - for uint::range(0u, workers) |i| { + for uint::range(0, workers) |_i| { let (to_child, from_parent_) = pipes::stream(); - from_parent.add(from_parent_); + from_parent.add(move from_parent_); do task::task().future_result(|+r| { - worker_results.push(r); - }).spawn { - for uint::range(0u, size / workers) |_i| { + worker_results.push(move r); + }).spawn |move to_child| { + for uint::range(0, size / workers) |_i| { //error!("worker %?: sending %? bytes", i, num_bytes); to_child.send(bytes(num_bytes)); } //error!("worker %? exiting", i); }; } - do task::spawn { + do task::spawn |move from_parent, move to_parent| { server(from_parent, to_parent); } diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs index f657884eeef8..3ec89567d206 100644 --- a/src/test/bench/msgsend-ring-mutex-arcs.rs +++ b/src/test/bench/msgsend-ring-mutex-arcs.rs @@ -33,7 +33,7 @@ fn recv(p: &pipe) -> uint { fn init() -> (pipe,pipe) { let m = arc::MutexARC(~[]); - ((&m).clone(), m) + ((&m).clone(), move m) } @@ -41,18 +41,18 @@ fn thread_ring(i: uint, count: uint, +num_chan: pipe, +num_port: pipe) { - let mut num_chan <- Some(num_chan); - let mut num_port <- Some(num_port); + let mut num_chan <- Some(move num_chan); + let mut num_port <- Some(move num_port); // Send/Receive lots of messages. for uint::range(0u, count) |j| { //error!("task %?, iter %?", i, j); let mut num_chan2 = option::swap_unwrap(&mut num_chan); let mut num_port2 = option::swap_unwrap(&mut num_port); send(&num_chan2, i * j); - num_chan = Some(num_chan2); + num_chan = Some(move num_chan2); let _n = recv(&num_port2); //log(error, _n); - num_port = Some(num_port2); + num_port = Some(move num_port2); }; } @@ -70,7 +70,7 @@ fn main() { let msg_per_task = uint::from_str(args[2]).get(); let (num_chan, num_port) = init(); - let mut num_chan = Some(num_chan); + let mut num_chan = Some(move num_chan); let start = time::precise_time_s(); @@ -82,22 +82,22 @@ fn main() { let (new_chan, num_port) = init(); let num_chan2 = ~mut None; *num_chan2 <-> num_chan; - let num_port = ~mut Some(num_port); + let num_port = ~mut Some(move num_port); let new_future = future::spawn(|move num_chan2, move num_port| { let mut num_chan = None; num_chan <-> *num_chan2; let mut num_port1 = None; num_port1 <-> *num_port; thread_ring(i, msg_per_task, - option::unwrap(num_chan), - option::unwrap(num_port1)) + option::unwrap(move num_chan), + option::unwrap(move num_port1)) }); - futures.push(new_future); - num_chan = Some(new_chan); + futures.push(move new_future); + num_chan = Some(move new_chan); }; // do our iteration - thread_ring(0u, msg_per_task, option::unwrap(num_chan), num_port); + thread_ring(0, msg_per_task, option::unwrap(move num_chan), move num_port); // synchronize for futures.each |f| { future::get(f) }; diff --git a/src/test/bench/msgsend-ring-pipes.rs b/src/test/bench/msgsend-ring-pipes.rs index 73942d4ddf8f..68429ee01bb7 100644 --- a/src/test/bench/msgsend-ring-pipes.rs +++ b/src/test/bench/msgsend-ring-pipes.rs @@ -24,7 +24,7 @@ proto! ring ( fn macros() { #macro[ [#move_out[x], - unsafe { let y <- *ptr::addr_of(&x); y }] + unsafe { let y <- *ptr::addr_of(&x); move y }] ]; } @@ -32,18 +32,18 @@ fn thread_ring(i: uint, count: uint, +num_chan: ring::client::num, +num_port: ring::server::num) { - let mut num_chan <- Some(num_chan); - let mut num_port <- Some(num_port); + let mut num_chan <- Some(move num_chan); + let mut num_port <- Some(move num_port); // Send/Receive lots of messages. - for uint::range(0u, count) |j| { + for uint::range(0, count) |j| { //error!("task %?, iter %?", i, j); let mut num_chan2 = None; let mut num_port2 = None; num_chan2 <-> num_chan; num_port2 <-> num_port; - num_chan = Some(ring::client::num(option::unwrap(num_chan2), i * j)); - let port = option::unwrap(num_port2); - match recv(port) { + num_chan = Some(ring::client::num(option::unwrap(move num_chan2), i * j)); + let port = option::unwrap(move num_port2); + match recv(move port) { ring::num(_n, p) => { //log(error, _n); num_port = Some(move_out!(p)); @@ -66,7 +66,7 @@ fn main() { let msg_per_task = uint::from_str(args[2]).get(); let (num_chan, num_port) = ring::init(); - let mut num_chan = Some(num_chan); + let mut num_chan = Some(move num_chan); let start = time::precise_time_s(); @@ -78,7 +78,7 @@ fn main() { let (new_chan, num_port) = ring::init(); let num_chan2 = ~mut None; *num_chan2 <-> num_chan; - let num_port = ~mut Some(num_port); + let num_port = ~mut Some(move num_port); let new_future = do future::spawn |move num_chan2, move num_port| { let mut num_chan = None; @@ -86,15 +86,15 @@ fn main() { let mut num_port1 = None; num_port1 <-> *num_port; thread_ring(i, msg_per_task, - option::unwrap(num_chan), - option::unwrap(num_port1)) + option::unwrap(move num_chan), + option::unwrap(move num_port1)) }; - futures.push(new_future); - num_chan = Some(new_chan); + futures.push(move new_future); + num_chan = Some(move new_chan); }; // do our iteration - thread_ring(0u, msg_per_task, option::unwrap(num_chan), num_port); + thread_ring(0, msg_per_task, option::unwrap(move num_chan), move num_port); // synchronize for futures.each |f| { future::get(f) }; diff --git a/src/test/bench/msgsend-ring-rw-arcs.rs b/src/test/bench/msgsend-ring-rw-arcs.rs index 386496f459d8..5e3d2f7d3e08 100644 --- a/src/test/bench/msgsend-ring-rw-arcs.rs +++ b/src/test/bench/msgsend-ring-rw-arcs.rs @@ -33,7 +33,7 @@ fn recv(p: &pipe) -> uint { fn init() -> (pipe,pipe) { let x = arc::RWARC(~[]); - ((&x).clone(), x) + ((&x).clone(), move x) } @@ -41,18 +41,18 @@ fn thread_ring(i: uint, count: uint, +num_chan: pipe, +num_port: pipe) { - let mut num_chan <- Some(num_chan); - let mut num_port <- Some(num_port); + let mut num_chan <- Some(move num_chan); + let mut num_port <- Some(move num_port); // Send/Receive lots of messages. for uint::range(0u, count) |j| { //error!("task %?, iter %?", i, j); let mut num_chan2 = option::swap_unwrap(&mut num_chan); let mut num_port2 = option::swap_unwrap(&mut num_port); send(&num_chan2, i * j); - num_chan = Some(num_chan2); + num_chan = Some(move num_chan2); let _n = recv(&num_port2); //log(error, _n); - num_port = Some(num_port2); + num_port = Some(move num_port2); }; } @@ -70,7 +70,7 @@ fn main() { let msg_per_task = uint::from_str(args[2]).get(); let (num_chan, num_port) = init(); - let mut num_chan = Some(num_chan); + let mut num_chan = Some(move num_chan); let start = time::precise_time_s(); @@ -82,7 +82,7 @@ fn main() { let (new_chan, num_port) = init(); let num_chan2 = ~mut None; *num_chan2 <-> num_chan; - let num_port = ~mut Some(num_port); + let num_port = ~mut Some(move num_port); let new_future = do future::spawn |move num_chan2, move num_port| { let mut num_chan = None; @@ -90,15 +90,15 @@ fn main() { let mut num_port1 = None; num_port1 <-> *num_port; thread_ring(i, msg_per_task, - option::unwrap(num_chan), - option::unwrap(num_port1)) + option::unwrap(move num_chan), + option::unwrap(move num_port1)) }; - futures.push(new_future); - num_chan = Some(new_chan); + futures.push(move new_future); + num_chan = Some(move new_chan); }; // do our iteration - thread_ring(0u, msg_per_task, option::unwrap(num_chan), num_port); + thread_ring(0, msg_per_task, option::unwrap(move num_chan), move num_port); // synchronize for futures.each |f| { future::get(f) }; diff --git a/src/test/bench/msgsend-ring.rs b/src/test/bench/msgsend-ring.rs index 1dfcd241b83b..5cb278b0dd2e 100644 --- a/src/test/bench/msgsend-ring.rs +++ b/src/test/bench/msgsend-ring.rs @@ -52,7 +52,7 @@ fn main() { get_chan_chan.send(Chan(&p)); thread_ring(i, msg_per_task, num_chan, p) }; - futures.push(new_future); + futures.push(move new_future); num_chan = get_chan.recv(); }; diff --git a/src/test/bench/msgsend.rs b/src/test/bench/msgsend.rs index 8564adaab729..6ab22779c55f 100644 --- a/src/test/bench/msgsend.rs +++ b/src/test/bench/msgsend.rs @@ -35,12 +35,12 @@ fn run(args: ~[~str]) { let workers = uint::from_str(args[2]).get(); let start = std::time::precise_time_s(); let mut worker_results = ~[]; - for uint::range(0u, workers) |_i| { + for uint::range(0, workers) |_i| { do task::task().future_result(|+r| { - worker_results.push(r); + worker_results.push(move r); }).spawn { - for uint::range(0u, size / workers) |_i| { - comm::send(to_child, bytes(100u)); + for uint::range(0, size / workers) |_i| { + comm::send(to_child, bytes(100)); } }; } diff --git a/src/test/bench/pingpong.rs b/src/test/bench/pingpong.rs index 8aa64fed3466..e7f9312ce386 100644 --- a/src/test/bench/pingpong.rs +++ b/src/test/bench/pingpong.rs @@ -33,7 +33,7 @@ proto! pingpong_unbounded ( // This stuff should go in libcore::pipes macro_rules! move_it ( - { $x:expr } => { let t <- *ptr::addr_of(&($x)); t } + { $x:expr } => { let t <- *ptr::addr_of(&($x)); move t } ) macro_rules! follow ( @@ -42,8 +42,8 @@ macro_rules! follow ( } => ( |m| match move m { $(Some($message($($x,)* move next)) => { - let $next = next; - $e })+ + let $next = move next; + move $e })+ _ => { fail } } ); @@ -53,8 +53,8 @@ macro_rules! follow ( } => ( |m| match move m { $(Some($message(move next)) => { - let $next = next; - $e })+ + let $next = move next; + move $e })+ _ => { fail } } ) @@ -62,7 +62,7 @@ macro_rules! follow ( fn switch(+endp: pipes::RecvPacketBuffered, f: fn(+v: Option) -> U) -> U { - f(pipes::try_recv(endp)) + f(pipes::try_recv(move endp)) } // Here's the benchmark @@ -72,10 +72,10 @@ fn bounded(count: uint) { let mut ch = do spawn_service(init) |ch| { let mut count = count; - let mut ch = ch; + let mut ch = move ch; while count > 0 { - ch = switch(ch, follow! ( - ping -> next { server::pong(next) } + ch = switch(move ch, follow! ( + ping -> next { server::pong(move next) } )); count -= 1; @@ -84,10 +84,10 @@ fn bounded(count: uint) { let mut count = count; while count > 0 { - let ch_ = client::ping(ch); + let ch_ = client::ping(move ch); - ch = switch(ch_, follow! ( - pong -> next { next } + ch = switch(move ch_, follow! ( + pong -> next { move next } )); count -= 1; @@ -99,10 +99,10 @@ fn unbounded(count: uint) { let mut ch = do spawn_service(init) |ch| { let mut count = count; - let mut ch = ch; + let mut ch = move ch; while count > 0 { - ch = switch(ch, follow! ( - ping -> next { server::pong(next) } + ch = switch(move ch, follow! ( + ping -> next { server::pong(move next) } )); count -= 1; @@ -111,10 +111,10 @@ fn unbounded(count: uint) { let mut count = count; while count > 0 { - let ch_ = client::ping(ch); + let ch_ = client::ping(move ch); - ch = switch(ch_, follow! ( - pong -> next { next } + ch = switch(move ch_, follow! ( + pong -> next { move next } )); count -= 1; diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 2e9f8e98dd37..9c5dd084d849 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -124,7 +124,7 @@ fn make_sequence_processor(sz: uint, from_parent: pipes::Port<~[u8]>, }; //comm::send(to_parent, fmt!("yay{%u}", sz)); - to_parent.send(buffer); + to_parent.send(move buffer); } // given a FASTA file on stdin, process sequence THREE @@ -143,25 +143,25 @@ fn main() { // initialize each sequence sorter - let sizes = ~[1u,2u,3u,4u,6u,12u,18u]; + let sizes = ~[1,2,3,4,6,12,18]; let streams = vec::map(sizes, |_sz| Some(stream())); - let streams = vec::to_mut(streams); + let streams = vec::to_mut(move streams); let mut from_child = ~[]; let to_child = vec::mapi(sizes, |ii, sz| { let sz = *sz; let mut stream = None; stream <-> streams[ii]; - let (to_parent_, from_child_) = option::unwrap(stream); + let (to_parent_, from_child_) = option::unwrap(move stream); - from_child.push(from_child_); + from_child.push(move from_child_); let (to_child, from_parent) = pipes::stream(); - do task::spawn_with(from_parent) |from_parent| { + do task::spawn_with(move from_parent) |move to_parent_, from_parent| { make_sequence_processor(sz, from_parent, to_parent_); }; - to_child + move to_child }); diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index fa97e796bd1c..a776c1322d38 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -34,15 +34,15 @@ fn fib(n: int) -> int { } else { let p = pipes::PortSet(); let ch = p.chan(); - task::spawn(|| pfib(ch, n - 1) ); + task::spawn(|move ch| pfib(ch, n - 1) ); let ch = p.chan(); - task::spawn(|| pfib(ch, n - 2) ); + task::spawn(|move ch| pfib(ch, n - 2) ); c.send(p.recv() + p.recv()); } } let (ch, p) = pipes::stream(); - let t = task::spawn(|| pfib(ch, n) ); + let _t = task::spawn(|move ch| pfib(ch, n) ); p.recv() } @@ -73,7 +73,7 @@ fn stress(num_tasks: int) { let mut results = ~[]; for range(0, num_tasks) |i| { do task::task().future_result(|+r| { - results.push(r); + results.push(move r); }).spawn { stress_task(i); } @@ -104,7 +104,7 @@ fn main() { let out = io::stdout(); for range(1, max + 1) |n| { - for range(0, num_trials) |i| { + for range(0, num_trials) |_i| { let start = time::precise_time_ns(); let fibn = fib(n); let stop = time::precise_time_ns(); diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs index f5b2bb1c1c37..55d75ff7c82d 100644 --- a/src/test/bench/task-perf-alloc-unwind.rs +++ b/src/test/bench/task-perf-alloc-unwind.rs @@ -78,7 +78,8 @@ fn recurse_or_fail(depth: int, st: Option) { box: @Cons((), st.box), unique: ~Cons((), @*st.unique), fn_box: fn@() -> @nillist { @Cons((), fn_box()) }, - fn_unique: fn~() -> ~nillist { ~Cons((), @*fn_unique()) }, + fn_unique: fn~(move fn_unique) -> ~nillist + { ~Cons((), @*fn_unique()) }, tuple: (@Cons((), st.tuple.first()), ~Cons((), @*st.tuple.second())), vec: st.vec + ~[@Cons((), st.vec.last())], @@ -87,6 +88,6 @@ fn recurse_or_fail(depth: int, st: Option) { } }; - recurse_or_fail(depth, Some(st)); + recurse_or_fail(depth, Some(move st)); } } diff --git a/src/test/bench/task-perf-jargon-metal-smoke.rs b/src/test/bench/task-perf-jargon-metal-smoke.rs index 2055993d441e..09e6f23004a1 100644 --- a/src/test/bench/task-perf-jargon-metal-smoke.rs +++ b/src/test/bench/task-perf-jargon-metal-smoke.rs @@ -9,14 +9,14 @@ fn child_generation(gens_left: uint, -c: pipes::Chan<()>) { // This used to be O(n^2) in the number of generations that ever existed. // With this code, only as many generations are alive at a time as tasks // alive at a time, - let c = ~mut Some(c); - do task::spawn_supervised { + let c = ~mut Some(move c); + do task::spawn_supervised |move c| { let c = option::swap_unwrap(c); if gens_left & 1 == 1 { task::yield(); // shake things up a bit } if gens_left > 0 { - child_generation(gens_left - 1, c); // recurse + child_generation(gens_left - 1, move c); // recurse } else { c.send(()) } @@ -27,14 +27,14 @@ fn main() { let args = os::args(); let args = if os::getenv(~"RUST_BENCH").is_some() { ~[~"", ~"100000"] - } else if args.len() <= 1u { + } else if args.len() <= 1 { ~[~"", ~"100"] } else { copy args }; let (c,p) = pipes::stream(); - child_generation(uint::from_str(args[1]).get(), c); + child_generation(uint::from_str(args[1]).get(), move c); if p.try_recv().is_none() { fail ~"it happened when we slumbered"; } diff --git a/src/test/bench/task-perf-linked-failure.rs b/src/test/bench/task-perf-linked-failure.rs index bd2c3d1bc077..f148d595f9d5 100644 --- a/src/test/bench/task-perf-linked-failure.rs +++ b/src/test/bench/task-perf-linked-failure.rs @@ -31,9 +31,9 @@ fn grandchild_group(num_tasks: uint) { fn spawn_supervised_blocking(myname: &str, +f: fn~()) { let mut res = None; - task::task().future_result(|+r| res = Some(r)).supervised().spawn(f); + task::task().future_result(|+r| res = Some(move r)).supervised().spawn(move f); error!("%s group waiting", myname); - let x = future::get(&option::unwrap(res)); + let x = future::get(&option::unwrap(move res)); assert x == task::Success; } diff --git a/src/test/bench/task-perf-word-count-generic.rs b/src/test/bench/task-perf-word-count-generic.rs index 30add8c730c7..3fe192ed3639 100644 --- a/src/test/bench/task-perf-word-count-generic.rs +++ b/src/test/bench/task-perf-word-count-generic.rs @@ -30,7 +30,7 @@ use cmp::Eq; use to_bytes::IterBytes; macro_rules! move_out ( - { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); y } } + { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } } ) trait word_reader { @@ -90,19 +90,19 @@ impl box { fn swap(f: fn(+v: T) -> T) { let mut tmp = None; self.contents <-> tmp; - self.contents = Some(f(option::unwrap(tmp))); + self.contents = Some(f(option::unwrap(move tmp))); } fn unwrap() -> T { let mut tmp = None; self.contents <-> tmp; - option::unwrap(tmp) + option::unwrap(move tmp) } } fn box(+x: T) -> box { box { - contents: Some(x) + contents: Some(move x) } } @@ -151,13 +151,13 @@ mod map_reduce { let mut tasks = ~[]; for inputs.each |i| { let (ctrl, ctrl_server) = ctrl_proto::init(); - let ctrl = box(ctrl); + let ctrl = box(move ctrl); let i = copy *i; let m = copy *map; - tasks.push(spawn_joinable(|move i| map_task(m, &ctrl, i))); - ctrls.push(ctrl_server); + tasks.push(spawn_joinable(|move ctrl, move i| map_task(m, &ctrl, i))); + ctrls.push(move ctrl_server); } - return tasks; + move tasks } fn map_task( @@ -177,8 +177,8 @@ mod map_reduce { Some(_c) => { c = Some(_c); } None => { do ctrl.swap |ctrl| { - let ctrl = ctrl_proto::client::find_reducer(ctrl, *key); - match pipes::recv(ctrl) { + let ctrl = ctrl_proto::client::find_reducer(move ctrl, *key); + match pipes::recv(move ctrl) { ctrl_proto::reducer(c_, ctrl) => { c = Some(c_); move_out!(ctrl) @@ -250,12 +250,12 @@ mod map_reduce { let mut num_mappers = vec::len(inputs) as int; while num_mappers > 0 { - let (_ready, message, ctrls) = pipes::select(ctrl); - match option::unwrap(message) { + let (_ready, message, ctrls) = pipes::select(move ctrl); + match option::unwrap(move message) { ctrl_proto::mapper_done => { // error!("received mapper terminated."); num_mappers -= 1; - ctrl = ctrls; + ctrl = move ctrls; } ctrl_proto::find_reducer(k, cc) => { let c; @@ -271,13 +271,13 @@ mod map_reduce { let p = Port(); let ch = Chan(&p); let r = reduce, kk = k; - tasks.push(spawn_joinable(|| reduce_task(~r, kk, ch) )); + tasks.push(spawn_joinable(|move r| reduce_task(~r, kk, ch) )); c = recv(p); reducers.insert(k, c); } } ctrl = vec::append_one( - ctrls, + move ctrls, ctrl_proto::server::reducer(move_out!(cc), c)); } } From 21453480903601700efb52c88a98e9428b03c4d3 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:44:46 -0700 Subject: [PATCH 187/292] Make moves explicit in cfail tests --- src/test/compile-fail/borrowck-loan-blocks-move.rs | 2 +- src/test/compile-fail/copy-into-closure.rs | 4 ++-- src/test/compile-fail/issue-1965.rs | 4 ++-- src/test/compile-fail/issue-2548.rs | 2 +- src/test/compile-fail/liveness-move-from-args.rs | 8 ++++---- src/test/compile-fail/liveness-move-from-mode.rs | 2 +- src/test/compile-fail/liveness-unused.rs | 2 +- src/test/compile-fail/liveness-use-after-send.rs | 2 +- src/test/compile-fail/unique-unique-kind.rs | 2 +- src/test/compile-fail/unsendable-class.rs | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/test/compile-fail/borrowck-loan-blocks-move.rs b/src/test/compile-fail/borrowck-loan-blocks-move.rs index 5cecbf9284fc..e48756bbbeb3 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-move.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-move.rs @@ -4,7 +4,7 @@ fn take(-_v: ~int) { fn box_imm() { let v = ~3; let _w = &v; //~ NOTE loan of immutable local variable granted here - take(v); //~ ERROR moving out of immutable local variable prohibited due to outstanding loan + take(move v); //~ ERROR moving out of immutable local variable prohibited due to outstanding loan } fn main() { diff --git a/src/test/compile-fail/copy-into-closure.rs b/src/test/compile-fail/copy-into-closure.rs index 8ee2a4fd3ae2..51e0934bfe00 100644 --- a/src/test/compile-fail/copy-into-closure.rs +++ b/src/test/compile-fail/copy-into-closure.rs @@ -4,7 +4,7 @@ fn closure1(+x: ~str) -> (~str, fn@() -> ~str) { //~^ WARNING implicitly copying a non-implicitly-copyable value //~^^ NOTE to copy values into a @fn closure, use a capture clause }; - (x,f) + (move x,f) } fn closure2(+x: util::NonCopyable) -> (util::NonCopyable, @@ -15,7 +15,7 @@ fn closure2(+x: util::NonCopyable) -> (util::NonCopyable, //~^^ NOTE non-copyable value cannot be copied into a @fn closure //~^^^ ERROR copying a noncopyable value }; - (x,f) + (move x,f) } fn closure3(+x: util::NonCopyable) { do task::spawn { diff --git a/src/test/compile-fail/issue-1965.rs b/src/test/compile-fail/issue-1965.rs index 9742acba1e31..ee318d7b02ca 100644 --- a/src/test/compile-fail/issue-1965.rs +++ b/src/test/compile-fail/issue-1965.rs @@ -2,6 +2,6 @@ fn test(-x: uint) {} fn main() { - let i = 3u; - for uint::range(0u, 10u) |_x| {test(i)} + let i = 3; + for uint::range(0, 10) |_x| {test(move i)} } diff --git a/src/test/compile-fail/issue-2548.rs b/src/test/compile-fail/issue-2548.rs index 61cfabc40d2d..0d491fc8834a 100644 --- a/src/test/compile-fail/issue-2548.rs +++ b/src/test/compile-fail/issue-2548.rs @@ -21,7 +21,7 @@ fn main() { let mut res = foo(x); let mut v = ~[mut]; - v <- ~[mut res] + v; //~ ERROR instantiating a type parameter with an incompatible type (needs `copy`, got `owned`, missing `copy`) + v <- ~[mut (move res)] + v; //~ ERROR instantiating a type parameter with an incompatible type (needs `copy`, got `owned`, missing `copy`) assert (v.len() == 2); } diff --git a/src/test/compile-fail/liveness-move-from-args.rs b/src/test/compile-fail/liveness-move-from-args.rs index 27e9d3b60dc9..48f72dd0d3e8 100644 --- a/src/test/compile-fail/liveness-move-from-args.rs +++ b/src/test/compile-fail/liveness-move-from-args.rs @@ -1,19 +1,19 @@ fn take(-_x: int) { } fn from_by_value_arg(++x: int) { - take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode + take(move x); //~ ERROR illegal move from argument `x`, which is not copy or move mode } fn from_by_ref_arg(&&x: int) { - take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode + take(move x); //~ ERROR illegal move from argument `x`, which is not copy or move mode } fn from_copy_arg(+x: int) { - take(x); + take(move x); } fn from_move_arg(-x: int) { - take(x); + take(move x); } fn main() { diff --git a/src/test/compile-fail/liveness-move-from-mode.rs b/src/test/compile-fail/liveness-move-from-mode.rs index a837d337f98d..959bda4e5834 100644 --- a/src/test/compile-fail/liveness-move-from-mode.rs +++ b/src/test/compile-fail/liveness-move-from-mode.rs @@ -4,7 +4,7 @@ fn main() { let x: int = 25; loop { - take(x); //~ ERROR use of moved variable: `x` + take(move x); //~ ERROR use of moved variable: `x` //~^ NOTE move of variable occurred here } } diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index 8b2fef7cd350..473a133730a4 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -54,5 +54,5 @@ struct r { } fn main() { let x = r { x: () }; - fn@() { copy x; }; //~ ERROR copying a noncopyable value + fn@(move x) { copy x; }; //~ ERROR copying a noncopyable value } diff --git a/src/test/compile-fail/liveness-use-after-send.rs b/src/test/compile-fail/liveness-use-after-send.rs index 5447c88e5676..13952dbe3c11 100644 --- a/src/test/compile-fail/liveness-use-after-send.rs +++ b/src/test/compile-fail/liveness-use-after-send.rs @@ -9,7 +9,7 @@ enum _chan = int; // Tests that "log(debug, message);" is flagged as using // message after the send deinitializes it fn test00_start(ch: _chan, message: int, _count: int) { - send(ch, message); //~ NOTE move of variable occurred here + send(ch, move message); //~ NOTE move of variable occurred here log(debug, message); //~ ERROR use of moved variable: `message` } diff --git a/src/test/compile-fail/unique-unique-kind.rs b/src/test/compile-fail/unique-unique-kind.rs index eea832c91a47..b31583724d21 100644 --- a/src/test/compile-fail/unique-unique-kind.rs +++ b/src/test/compile-fail/unique-unique-kind.rs @@ -3,5 +3,5 @@ fn f(_i: T) { fn main() { let i = ~@100; - f(i); //~ ERROR missing `send` + f(move i); //~ ERROR missing `send` } diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs index a47a8b76e56a..a84c1397319f 100644 --- a/src/test/compile-fail/unsendable-class.rs +++ b/src/test/compile-fail/unsendable-class.rs @@ -17,5 +17,5 @@ fn main() { let cat = ~"kitty"; let po = comm::Port(); //~ ERROR missing `send` let ch = comm::Chan(&po); //~ ERROR missing `send` - comm::send(ch, foo(42, @cat)); //~ ERROR missing `send` + comm::send(ch, foo(42, @(move cat))); //~ ERROR missing `send` } From 3ebd878f4a01e8f66dee09e054c6c0c39384afd8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:45:24 -0700 Subject: [PATCH 188/292] Make moves explicit in rpass tests --- src/test/run-pass/argument-passing.rs | 2 +- src/test/run-pass/auto-ref-sliceable.rs | 2 +- src/test/run-pass/fn-bare-spawn.rs | 2 +- src/test/run-pass/functional-struct-update.rs | 2 +- src/test/run-pass/intrinsic-move-val.rs | 2 +- src/test/run-pass/issue-2185.rs | 2 +- src/test/run-pass/issue-2718.rs | 60 ++++++++++--------- src/test/run-pass/issue-2834.rs | 2 +- src/test/run-pass/issue-2904.rs | 2 +- src/test/run-pass/issue-2930.rs | 2 +- src/test/run-pass/issue-3168.rs | 8 +-- src/test/run-pass/issue-3176.rs | 10 ++-- src/test/run-pass/issue-3668.rs | 1 + src/test/run-pass/issue-3688-2.rs | 7 ++- src/test/run-pass/last-use-corner-cases.rs | 2 +- src/test/run-pass/last-use-in-block.rs | 4 +- src/test/run-pass/liveness-move-in-loop.rs | 2 +- src/test/run-pass/log-linearized.rs | 2 +- ...nomorphized-callees-with-ty-params-3314.rs | 2 +- src/test/run-pass/move-arg-2-unique.rs | 2 +- src/test/run-pass/move-arg-2.rs | 2 +- src/test/run-pass/move-arg.rs | 2 +- src/test/run-pass/move-nullary-fn.rs | 2 +- src/test/run-pass/non-legacy-modes.rs | 2 +- src/test/run-pass/option-unwrap.rs | 4 +- src/test/run-pass/pipe-bank-proto.rs | 30 +++++----- src/test/run-pass/pipe-detect-term.rs | 6 +- src/test/run-pass/pipe-peek.rs | 2 +- src/test/run-pass/pipe-pingpong-bounded.rs | 30 +++++----- src/test/run-pass/pipe-pingpong-proto.rs | 16 ++--- .../run-pass/pipe-presentation-examples.rs | 18 +++--- src/test/run-pass/pipe-select-macro.rs | 2 + src/test/run-pass/pipe-select.rs | 32 +++++----- src/test/run-pass/pipe-sleep.rs | 4 +- src/test/run-pass/regions-copy-closure.rs | 4 +- src/test/run-pass/regions-static-closure.rs | 6 +- .../run-pass/resource-assign-is-not-copy.rs | 4 +- src/test/run-pass/resource-cycle.rs | 8 +-- src/test/run-pass/resource-cycle2.rs | 4 +- src/test/run-pass/resource-cycle3.rs | 4 +- src/test/run-pass/rt-sched-1.rs | 2 +- src/test/run-pass/select-macro.rs | 12 ++-- src/test/run-pass/static-method-test.rs | 4 +- src/test/run-pass/task-comm-0.rs | 2 +- src/test/run-pass/task-comm-10.rs | 6 +- src/test/run-pass/task-comm-11.rs | 4 +- src/test/run-pass/task-comm-12.rs | 4 +- src/test/run-pass/task-comm-13.rs | 2 +- src/test/run-pass/task-comm-14.rs | 4 +- src/test/run-pass/task-comm-15.rs | 2 +- src/test/run-pass/task-comm-16.rs | 2 +- src/test/run-pass/task-comm-3.rs | 4 +- src/test/run-pass/task-comm-7.rs | 8 +-- src/test/run-pass/task-comm-9.rs | 5 +- src/test/run-pass/task-comm.rs | 4 +- src/test/run-pass/trait-to-str.rs | 2 +- src/test/run-pass/unique-fn-arg-move.rs | 2 +- src/test/run-pass/yield.rs | 4 +- src/test/run-pass/yield1.rs | 4 +- 59 files changed, 192 insertions(+), 185 deletions(-) diff --git a/src/test/run-pass/argument-passing.rs b/src/test/run-pass/argument-passing.rs index e8aaf88374f9..dc861829c11c 100644 --- a/src/test/run-pass/argument-passing.rs +++ b/src/test/run-pass/argument-passing.rs @@ -12,7 +12,7 @@ fn f2(a: int, f: fn(int)) -> int { f(1); return a; } fn main() { let mut a = {mut x: 1}, b = 2, c = 3; - assert (f1(a, &mut b, c) == 6); + assert (f1(a, &mut b, move c) == 6); assert (a.x == 0); assert (b == 10); assert (f2(a.x, |x| a.x = 50 ) == 0); diff --git a/src/test/run-pass/auto-ref-sliceable.rs b/src/test/run-pass/auto-ref-sliceable.rs index 48d83da74adb..a8e6832d33cc 100644 --- a/src/test/run-pass/auto-ref-sliceable.rs +++ b/src/test/run-pass/auto-ref-sliceable.rs @@ -4,7 +4,7 @@ trait Pushable { impl ~[T]: Pushable { fn push_val(&mut self, +t: T) { - self.push(t); + self.push(move t); } } diff --git a/src/test/run-pass/fn-bare-spawn.rs b/src/test/run-pass/fn-bare-spawn.rs index 2655b0260fdd..f50d74a2df25 100644 --- a/src/test/run-pass/fn-bare-spawn.rs +++ b/src/test/run-pass/fn-bare-spawn.rs @@ -1,7 +1,7 @@ // This is what the signature to spawn should look like with bare functions fn spawn(val: T, f: extern fn(T)) { - f(val); + f(move val); } fn f(+i: int) { diff --git a/src/test/run-pass/functional-struct-update.rs b/src/test/run-pass/functional-struct-update.rs index ce6198c8d244..e95027a4246a 100644 --- a/src/test/run-pass/functional-struct-update.rs +++ b/src/test/run-pass/functional-struct-update.rs @@ -5,7 +5,7 @@ struct Foo { fn main() { let a = Foo { x: 1, y: 2 }; - let c = Foo { x: 4, .. a }; + let c = Foo { x: 4, .. a}; io::println(fmt!("%?", c)); } diff --git a/src/test/run-pass/intrinsic-move-val.rs b/src/test/run-pass/intrinsic-move-val.rs index 683321aac3d0..e32656894a8a 100644 --- a/src/test/run-pass/intrinsic-move-val.rs +++ b/src/test/run-pass/intrinsic-move-val.rs @@ -8,6 +8,6 @@ extern mod rusti { fn main() { let mut x = @1; let mut y = @2; - rusti::move_val(&mut y, x); + rusti::move_val(&mut y, move x); assert *y == 1; } \ No newline at end of file diff --git a/src/test/run-pass/issue-2185.rs b/src/test/run-pass/issue-2185.rs index 3b3b63308cd4..cda85fb166a9 100644 --- a/src/test/run-pass/issue-2185.rs +++ b/src/test/run-pass/issue-2185.rs @@ -28,7 +28,7 @@ fn foldl>(self: IA, +b0: B, blk: fn(B, A) -> B) -> B { do self.iter |a| { b <- blk(b, a); } - return b; + move b } fn range(lo: uint, hi: uint, it: fn(uint)) { diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index b887b86cf2f3..e91194b009a2 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -1,3 +1,5 @@ +// tjc: I don't know why +// xfail-pretty mod pipes { #[legacy_exports]; use cast::{forget, transmute}; @@ -42,18 +44,18 @@ mod pipes { // We should consider moving this to core::unsafe, although I // suspect graydon would want us to use void pointers instead. unsafe fn uniquify(+x: *T) -> ~T { - unsafe { cast::transmute(x) } + unsafe { cast::transmute(move x) } } fn swap_state_acq(+dst: &mut state, src: state) -> state { unsafe { - transmute(rusti::atomic_xchg_acq(transmute(dst), src as int)) + transmute(rusti::atomic_xchg_acq(transmute(move dst), src as int)) } } fn swap_state_rel(+dst: &mut state, src: state) -> state { unsafe { - transmute(rusti::atomic_xchg_rel(transmute(dst), src as int)) + transmute(rusti::atomic_xchg_rel(transmute(move dst), src as int)) } } @@ -61,20 +63,20 @@ mod pipes { let p = p.unwrap(); let p = unsafe { uniquify(p) }; assert (*p).payload.is_none(); - (*p).payload <- Some(payload); + (*p).payload <- Some(move payload); let old_state = swap_state_rel(&mut (*p).state, full); match old_state { empty => { // Yay, fastpath. // The receiver will eventually clean this up. - unsafe { forget(p); } + unsafe { forget(move p); } } full => { fail ~"duplicate send" } blocked => { // The receiver will eventually clean this up. - unsafe { forget(p); } + unsafe { forget(move p); } } terminated => { // The receiver will never receive this. Rely on drop_glue @@ -94,7 +96,7 @@ mod pipes { full => { let mut payload = None; payload <-> (*p).payload; - return Some(option::unwrap(payload)) + return Some(option::unwrap(move payload)) } terminated => { assert old_state == terminated; @@ -109,7 +111,7 @@ mod pipes { match swap_state_rel(&mut (*p).state, terminated) { empty | blocked => { // The receiver will eventually clean up. - unsafe { forget(p) } + unsafe { forget(move p) } } full => { // This is impossible @@ -126,7 +128,7 @@ mod pipes { match swap_state_rel(&mut (*p).state, terminated) { empty => { // the sender will clean up - unsafe { forget(p) } + unsafe { forget(move p) } } blocked => { // this shouldn't happen. @@ -144,7 +146,7 @@ mod pipes { if self.p != None { let mut p = None; p <-> self.p; - sender_terminate(option::unwrap(p)) + sender_terminate(option::unwrap(move p)) } } } @@ -153,7 +155,7 @@ mod pipes { fn unwrap() -> *packet { let mut p = None; p <-> self.p; - option::unwrap(p) + option::unwrap(move p) } } @@ -169,7 +171,7 @@ mod pipes { if self.p != None { let mut p = None; p <-> self.p; - receiver_terminate(option::unwrap(p)) + receiver_terminate(option::unwrap(move p)) } } } @@ -178,7 +180,7 @@ mod pipes { fn unwrap() -> *packet { let mut p = None; p <-> self.p; - option::unwrap(p) + option::unwrap(move p) } } @@ -204,8 +206,8 @@ mod pingpong { ping(x) => { cast::transmute(ptr::addr_of(&x)) } }; let liberated_value <- *addr; - cast::forget(p); - liberated_value + cast::forget(move p); + move liberated_value } fn liberate_pong(-p: pong) -> pipes::send_packet unsafe { @@ -213,8 +215,8 @@ mod pingpong { pong(x) => { cast::transmute(ptr::addr_of(&x)) } }; let liberated_value <- *addr; - cast::forget(p); - liberated_value + cast::forget(move p); + move liberated_value } fn init() -> (client::ping, server::ping) { @@ -229,16 +231,16 @@ mod pingpong { fn do_ping(-c: ping) -> pong { let (sp, rp) = pipes::entangle(); - pipes::send(c, ping(sp)); - rp + pipes::send(move c, ping(move sp)); + move rp } fn do_pong(-c: pong) -> (ping, ()) { - let packet = pipes::recv(c); + let packet = pipes::recv(move c); if packet.is_none() { fail ~"sender closed the connection" } - (liberate_pong(option::unwrap(packet)), ()) + (liberate_pong(option::unwrap(move packet)), ()) } } @@ -248,32 +250,32 @@ mod pingpong { type pong = pipes::send_packet; fn do_ping(-c: ping) -> (pong, ()) { - let packet = pipes::recv(c); + let packet = pipes::recv(move c); if packet.is_none() { fail ~"sender closed the connection" } - (liberate_ping(option::unwrap(packet)), ()) + (liberate_ping(option::unwrap(move packet)), ()) } fn do_pong(-c: pong) -> ping { let (sp, rp) = pipes::entangle(); - pipes::send(c, pong(sp)); - rp + pipes::send(move c, pong(move sp)); + move rp } } } fn client(-chan: pingpong::client::ping) { - let chan = pingpong::client::do_ping(chan); + let chan = pingpong::client::do_ping(move chan); log(error, ~"Sent ping"); - let (chan, _data) = pingpong::client::do_pong(chan); + let (_chan, _data) = pingpong::client::do_pong(move chan); log(error, ~"Received pong"); } fn server(-chan: pingpong::server::ping) { - let (chan, _data) = pingpong::server::do_ping(chan); + let (chan, _data) = pingpong::server::do_ping(move chan); log(error, ~"Received ping"); - let chan = pingpong::server::do_pong(chan); + let _chan = pingpong::server::do_pong(move chan); log(error, ~"Sent pong"); } diff --git a/src/test/run-pass/issue-2834.rs b/src/test/run-pass/issue-2834.rs index b61169ee5f6d..096ee2eed48e 100644 --- a/src/test/run-pass/issue-2834.rs +++ b/src/test/run-pass/issue-2834.rs @@ -9,7 +9,7 @@ proto! streamp ( fn rendezvous() { let (c, s) = streamp::init(); - let streams: ~[streamp::client::open] = ~[c]; + let streams: ~[streamp::client::open] = ~[move c]; error!("%?", streams[0]); } diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index b03cab1a828f..5cc39f4d683d 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -48,7 +48,7 @@ fn square_from_char(c: char) -> square { } fn read_board_grid(+in: rdr) -> ~[~[square]] { - let in = in as io::Reader; + let in = (move in) as io::Reader; let mut grid = ~[]; for in.each_line |line| { let mut row = ~[]; diff --git a/src/test/run-pass/issue-2930.rs b/src/test/run-pass/issue-2930.rs index 98cfaded04a9..c480d382adc0 100644 --- a/src/test/run-pass/issue-2930.rs +++ b/src/test/run-pass/issue-2930.rs @@ -7,5 +7,5 @@ proto! stream ( fn main() { let (bc, _bp) = stream::init(); - stream::client::send(bc, ~"abc"); + stream::client::send(move bc, ~"abc"); } diff --git a/src/test/run-pass/issue-3168.rs b/src/test/run-pass/issue-3168.rs index 3154daffb23e..44a96a276ea5 100644 --- a/src/test/run-pass/issue-3168.rs +++ b/src/test/run-pass/issue-3168.rs @@ -2,15 +2,15 @@ fn main() { let (c,p) = pipes::stream(); - do task::try { + do task::try |move c| { let (c2,p2) = pipes::stream(); - do task::spawn { + do task::spawn |move p2| { p2.recv(); - error!("brother fails"); + error!("sibling fails"); fail; } let (c3,p3) = pipes::stream(); - c.send(c3); + c.send(move c3); c2.send(()); error!("child blocks"); p3.recv(); diff --git a/src/test/run-pass/issue-3176.rs b/src/test/run-pass/issue-3176.rs index 7f89f4c49b70..17e6c03c9541 100644 --- a/src/test/run-pass/issue-3176.rs +++ b/src/test/run-pass/issue-3176.rs @@ -4,19 +4,19 @@ use pipes::{Select2, Selectable}; fn main() { let (c,p) = pipes::stream(); - do task::try { + do task::try |move c| { let (c2,p2) = pipes::stream(); - do task::spawn { + do task::spawn |move p2| { p2.recv(); - error!("brother fails"); + error!("sibling fails"); fail; } let (c3,p3) = pipes::stream(); - c.send(c3); + c.send(move c3); c2.send(()); error!("child blocks"); let (c, p) = pipes::stream(); - (p, p3).select(); + (move p, move p3).select(); c.send(()); }; error!("parent tries"); diff --git a/src/test/run-pass/issue-3668.rs b/src/test/run-pass/issue-3668.rs index 5f677767240d..8b3005a3589d 100644 --- a/src/test/run-pass/issue-3668.rs +++ b/src/test/run-pass/issue-3668.rs @@ -1,3 +1,4 @@ +// xfail-test struct P { child: Option<@mut P> } trait PTrait { fn getChildOption() -> Option<@P>; diff --git a/src/test/run-pass/issue-3688-2.rs b/src/test/run-pass/issue-3688-2.rs index 018bd1d2a8d3..8a5b0e26829c 100644 --- a/src/test/run-pass/issue-3688-2.rs +++ b/src/test/run-pass/issue-3688-2.rs @@ -1,5 +1,6 @@ - fn f(x:int) { - const child: int = x + 1; - } +// xfail-test +fn f(x:int) { + const child: int = x + 1; +} fn main() {} diff --git a/src/test/run-pass/last-use-corner-cases.rs b/src/test/run-pass/last-use-corner-cases.rs index a3088a2c1256..510fc8ddeaa0 100644 --- a/src/test/run-pass/last-use-corner-cases.rs +++ b/src/test/run-pass/last-use-corner-cases.rs @@ -5,7 +5,7 @@ fn main() { // Make sure closing over can be a last use let q = ~10; let addr = ptr::addr_of(&(*q)); - let f = fn@() -> *int { ptr::addr_of(&(*q)) }; + let f = fn@(move q) -> *int { ptr::addr_of(&(*q)) }; assert addr == f(); // But only when it really is the last use diff --git a/src/test/run-pass/last-use-in-block.rs b/src/test/run-pass/last-use-in-block.rs index c1dc0b76a10b..56c6659743d8 100644 --- a/src/test/run-pass/last-use-in-block.rs +++ b/src/test/run-pass/last-use-in-block.rs @@ -3,14 +3,14 @@ fn lp(s: ~str, f: fn(~str) -> T) -> T { while false { let r = f(s); - return r; + return (move r); } fail; } fn apply(s: ~str, f: fn(~str) -> T) -> T { fn g(s: ~str, f: fn(~str) -> T) -> T {f(s)} - g(s, |v| { let r = f(v); r }) + g(s, |v| { let r = f(v); move r }) } fn main() {} diff --git a/src/test/run-pass/liveness-move-in-loop.rs b/src/test/run-pass/liveness-move-in-loop.rs index e0a05c9b2976..d52395b4c7ca 100644 --- a/src/test/run-pass/liveness-move-in-loop.rs +++ b/src/test/run-pass/liveness-move-in-loop.rs @@ -5,7 +5,7 @@ fn the_loop() { loop { let x = 5; if x > 3 { - list += ~[take(x)]; + list += ~[take(move x)]; } else { break; } diff --git a/src/test/run-pass/log-linearized.rs b/src/test/run-pass/log-linearized.rs index bb042f2359b2..bb9a42784674 100644 --- a/src/test/run-pass/log-linearized.rs +++ b/src/test/run-pass/log-linearized.rs @@ -9,7 +9,7 @@ type smallintmap = @{mut v: ~[mut option]}; fn mk() -> smallintmap { let v: ~[mut option] = ~[mut]; - return @{mut v: v}; + return @{mut v: move v}; } fn f() { diff --git a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs index c771249c9ed6..eed871ce4b86 100644 --- a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs +++ b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs @@ -15,7 +15,7 @@ struct F { a: A } impl F: Serializable { fn serialize(s: S) { - self.a.serialize(s); + self.a.serialize(move s); } } diff --git a/src/test/run-pass/move-arg-2-unique.rs b/src/test/run-pass/move-arg-2-unique.rs index e312d2afb4b8..fded13293f39 100644 --- a/src/test/run-pass/move-arg-2-unique.rs +++ b/src/test/run-pass/move-arg-2-unique.rs @@ -3,7 +3,7 @@ fn test(-foo: ~~[int]) { assert (foo[0] == 10); } fn main() { let x = ~~[10]; // Test forgetting a local by move-in - test(x); + test(move x); // Test forgetting a temporary by move-in. test(~~[10]); diff --git a/src/test/run-pass/move-arg-2.rs b/src/test/run-pass/move-arg-2.rs index 01e287c0db09..1f2f3b9ad3b2 100644 --- a/src/test/run-pass/move-arg-2.rs +++ b/src/test/run-pass/move-arg-2.rs @@ -3,7 +3,7 @@ fn test(-foo: @~[int]) { assert (foo[0] == 10); } fn main() { let x = @~[10]; // Test forgetting a local by move-in - test(x); + test(move x); // Test forgetting a temporary by move-in. test(@~[10]); diff --git a/src/test/run-pass/move-arg.rs b/src/test/run-pass/move-arg.rs index 286b7c6cb6db..1db4d9cef748 100644 --- a/src/test/run-pass/move-arg.rs +++ b/src/test/run-pass/move-arg.rs @@ -1,3 +1,3 @@ fn test(-foo: int) { assert (foo == 10); } -fn main() { let x = 10; test(x); } +fn main() { let x = 10; test(move x); } diff --git a/src/test/run-pass/move-nullary-fn.rs b/src/test/run-pass/move-nullary-fn.rs index e5331a11556c..0c02affb1c5a 100644 --- a/src/test/run-pass/move-nullary-fn.rs +++ b/src/test/run-pass/move-nullary-fn.rs @@ -2,7 +2,7 @@ fn f2(-thing: fn@()) { } fn f(-thing: fn@()) { - f2(thing); + f2(move thing); } fn main() { diff --git a/src/test/run-pass/non-legacy-modes.rs b/src/test/run-pass/non-legacy-modes.rs index 8fb843d8564a..d6ece2c19c35 100644 --- a/src/test/run-pass/non-legacy-modes.rs +++ b/src/test/run-pass/non-legacy-modes.rs @@ -3,7 +3,7 @@ struct X { } fn apply(x: T, f: fn(T)) { - f(x); + f(move x); } fn check_int(x: int) { diff --git a/src/test/run-pass/option-unwrap.rs b/src/test/run-pass/option-unwrap.rs index 06b87794e595..7481b06d873d 100644 --- a/src/test/run-pass/option-unwrap.rs +++ b/src/test/run-pass/option-unwrap.rs @@ -9,7 +9,7 @@ struct dtor { fn unwrap(+o: Option) -> T { match move o { - Some(move v) => v, + Some(move v) => move v, None => fail } } @@ -19,7 +19,7 @@ fn main() { { let b = Some(dtor { x:x }); - let c = unwrap(b); + let c = unwrap(move b); } assert *x == 0; diff --git a/src/test/run-pass/pipe-bank-proto.rs b/src/test/run-pass/pipe-bank-proto.rs index 899b74b2866e..e59634ad0897 100644 --- a/src/test/run-pass/pipe-bank-proto.rs +++ b/src/test/run-pass/pipe-bank-proto.rs @@ -33,15 +33,15 @@ proto! bank ( ) macro_rules! move_it ( - { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); y } } + { $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } } ) fn switch(+endp: pipes::RecvPacket, f: fn(+v: Option) -> U) -> U { - f(pipes::try_recv(endp)) + f(pipes::try_recv(move endp)) } -fn move_it(-x: T) -> T { x } +fn move_it(-x: T) -> T { move x } macro_rules! follow ( { @@ -59,15 +59,15 @@ macro_rules! follow ( fn client_follow(+bank: bank::client::login) { use bank::*; - let bank = client::login(bank, ~"theincredibleholk", ~"1234"); - let bank = switch(bank, follow! ( - ok -> connected { connected } + let bank = client::login(move bank, ~"theincredibleholk", ~"1234"); + let bank = switch(move bank, follow! ( + ok -> connected { move connected } invalid -> _next { fail ~"bank closed the connected" } )); - let bank = client::deposit(bank, 100.00); - let bank = client::withdrawal(bank, 50.00); - switch(bank, follow! ( + let bank = client::deposit(move bank, 100.00); + let bank = client::withdrawal(move bank, 50.00); + switch(move bank, follow! ( money(m) -> _next { io::println(~"Yay! I got money!"); } @@ -80,8 +80,8 @@ fn client_follow(+bank: bank::client::login) { fn bank_client(+bank: bank::client::login) { use bank::*; - let bank = client::login(bank, ~"theincredibleholk", ~"1234"); - let bank = match try_recv(bank) { + let bank = client::login(move bank, ~"theincredibleholk", ~"1234"); + let bank = match try_recv(move bank) { Some(ok(connected)) => { move_it!(connected) } @@ -89,10 +89,10 @@ fn bank_client(+bank: bank::client::login) { None => { fail ~"bank closed the connection" } }; - let bank = client::deposit(bank, 100.00); - let bank = client::withdrawal(bank, 50.00); - match try_recv(bank) { - Some(money(m, _)) => { + let bank = client::deposit(move bank, 100.00); + let bank = client::withdrawal(move bank, 50.00); + match try_recv(move bank) { + Some(money(*)) => { io::println(~"Yay! I got money!"); } Some(insufficient_funds(_)) => { diff --git a/src/test/run-pass/pipe-detect-term.rs b/src/test/run-pass/pipe-detect-term.rs index 93c12449f2eb..524541780c07 100644 --- a/src/test/run-pass/pipe-detect-term.rs +++ b/src/test/run-pass/pipe-detect-term.rs @@ -19,7 +19,7 @@ fn main() { let iotask = uv::global_loop::get(); pipes::spawn_service(oneshot::init, |p| { - match try_recv(p) { + match try_recv(move p) { Some(*) => { fail } None => { } } @@ -34,11 +34,11 @@ fn main() { fn failtest() { let (c, p) = oneshot::init(); - do task::spawn_with(c) |_c| { + do task::spawn_with(move c) |_c| { fail; } - error!("%?", recv(p)); + error!("%?", recv(move p)); // make sure we get killed if we missed it in the receive. loop { task::yield() } } diff --git a/src/test/run-pass/pipe-peek.rs b/src/test/run-pass/pipe-peek.rs index e8b2aa1a791a..e3a2d29747b6 100644 --- a/src/test/run-pass/pipe-peek.rs +++ b/src/test/run-pass/pipe-peek.rs @@ -15,7 +15,7 @@ fn main() { assert !pipes::peek(&p); - oneshot::client::signal(c); + oneshot::client::signal(move c); assert pipes::peek(&p); } diff --git a/src/test/run-pass/pipe-pingpong-bounded.rs b/src/test/run-pass/pipe-pingpong-bounded.rs index 9bfbbe338e76..0db7d6cf123a 100644 --- a/src/test/run-pass/pipe-pingpong-bounded.rs +++ b/src/test/run-pass/pipe-pingpong-bounded.rs @@ -25,7 +25,7 @@ mod pingpong { pong: mk_packet::() } }; - do pipes::entangle_buffer(buffer) |buffer, data| { + do pipes::entangle_buffer(move buffer) |buffer, data| { data.ping.set_buffer_(buffer); data.pong.set_buffer_(buffer); ptr::addr_of(&(data.ping)) @@ -40,9 +40,9 @@ mod pingpong { let b = pipe.reuse_buffer(); let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.pong))); let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.pong))); - let message = pingpong::ping(s); - pipes::send(pipe, message); - c + let message = pingpong::ping(move s); + pipes::send(move pipe, move message); + move c } } type ping = pipes::SendPacketBuffered client__; - test::client(option::unwrap(client__)); + test::client(option::unwrap(move client__)); }; do task::spawn |move server_| { let mut server_ˊ = None; *server_ <-> server_ˊ; - test::server(option::unwrap(server_ˊ)); + test::server(option::unwrap(move server_ˊ)); }; } diff --git a/src/test/run-pass/pipe-pingpong-proto.rs b/src/test/run-pass/pipe-pingpong-proto.rs index 7af00e8dbf2c..c1c74aefa9c8 100644 --- a/src/test/run-pass/pipe-pingpong-proto.rs +++ b/src/test/run-pass/pipe-pingpong-proto.rs @@ -20,35 +20,35 @@ mod test { fn client(-chan: pingpong::client::ping) { use pingpong::client; - let chan = client::ping(chan); + let chan = client::ping(move chan); log(error, ~"Sent ping"); - let pong(_chan) = recv(chan); + let pong(_chan) = recv(move chan); log(error, ~"Received pong"); } fn server(-chan: pingpong::server::ping) { use pingpong::server; - let ping(chan) = recv(chan); + let ping(chan) = recv(move chan); log(error, ~"Received ping"); - let _chan = server::pong(chan); + let _chan = server::pong(move chan); log(error, ~"Sent pong"); } } fn main() { let (client_, server_) = pingpong::init(); - let client_ = ~mut Some(client_); - let server_ = ~mut Some(server_); + let client_ = ~mut Some(move client_); + let server_ = ~mut Some(move server_); do task::spawn |move client_| { let mut client__ = None; *client_ <-> client__; - test::client(option::unwrap(client__)); + test::client(option::unwrap(move client__)); }; do task::spawn |move server_| { let mut server_ˊ = None; *server_ <-> server_ˊ; - test::server(option::unwrap(server_ˊ)); + test::server(option::unwrap(move server_ˊ)); }; } diff --git a/src/test/run-pass/pipe-presentation-examples.rs b/src/test/run-pass/pipe-presentation-examples.rs index f485148d79e9..7ce8e6ea73d0 100644 --- a/src/test/run-pass/pipe-presentation-examples.rs +++ b/src/test/run-pass/pipe-presentation-examples.rs @@ -22,10 +22,10 @@ macro_rules! select_if ( ], )* } => { if $index == $count { - match move pipes::try_recv($port) { + match move pipes::try_recv(move $port) { $(Some($message($($(move $x,)+)* move next)) => { - let $next = next; - $e + let $next = move next; + move $e })+ _ => fail } @@ -90,33 +90,33 @@ fn render(_buffer: &Buffer) { } fn draw_frame(+channel: double_buffer::client::acquire) { - let channel = request(channel); + let channel = request(move channel); select! ( channel => { give_buffer(buffer) -> channel { render(&buffer); - release(channel, move buffer) + release(move channel, move buffer) } } ); } fn draw_two_frames(+channel: double_buffer::client::acquire) { - let channel = request(channel); + let channel = request(move channel); let channel = select! ( channel => { give_buffer(buffer) -> channel { render(&buffer); - release(channel, move buffer) + release(move channel, move buffer) } } ); - let channel = request(channel); + let channel = request(move channel); select! ( channel => { give_buffer(buffer) -> channel { render(&buffer); - release(channel, move buffer) + release(move channel, move buffer) } } ); diff --git a/src/test/run-pass/pipe-select-macro.rs b/src/test/run-pass/pipe-select-macro.rs index bc99ac788e0e..e3842c86c4c4 100644 --- a/src/test/run-pass/pipe-select-macro.rs +++ b/src/test/run-pass/pipe-select-macro.rs @@ -1,3 +1,5 @@ +// tjc: un-xfail after snapshot +// xfail-test // xfail-pretty // Protocols diff --git a/src/test/run-pass/pipe-select.rs b/src/test/run-pass/pipe-select.rs index 4d70eb62e948..627cdbee9cab 100644 --- a/src/test/run-pass/pipe-select.rs +++ b/src/test/run-pass/pipe-select.rs @@ -27,24 +27,24 @@ fn main() { let c = pipes::spawn_service(stream::init, |p| { error!("waiting for pipes"); - let stream::send(x, p) = recv(p); + let stream::send(x, p) = recv(move p); error!("got pipes"); let (left, right) : (oneshot::server::waiting, oneshot::server::waiting) - = x; + = move x; error!("selecting"); - let (i, _, _) = select(~[left, right]); + let (i, _, _) = select(~[move left, move right]); error!("selected"); assert i == 0; error!("waiting for pipes"); - let stream::send(x, _) = recv(p); + let stream::send(x, _) = recv(move p); error!("got pipes"); let (left, right) : (oneshot::server::waiting, oneshot::server::waiting) - = x; + = move x; error!("selecting"); - let (i, m, _) = select(~[left, right]); + let (i, m, _) = select(~[move left, move right]); error!("selected %?", i); if m.is_some() { assert i == 1; @@ -54,20 +54,20 @@ fn main() { let (c1, p1) = oneshot::init(); let (_c2, p2) = oneshot::init(); - let c = send(c, (p1, p2)); + let c = send(move c, (move p1, move p2)); sleep(iotask, 100); - signal(c1); + signal(move c1); let (_c1, p1) = oneshot::init(); let (c2, p2) = oneshot::init(); - send(c, (p1, p2)); + send(move c, (move p1, move p2)); sleep(iotask, 100); - signal(c2); + signal(move c2); test_select2(); } @@ -76,26 +76,26 @@ fn test_select2() { let (ac, ap) = stream::init(); let (bc, bp) = stream::init(); - stream::client::send(ac, 42); + stream::client::send(move ac, 42); - match pipes::select2(ap, bp) { + match pipes::select2(move ap, move bp) { either::Left(*) => { } either::Right(*) => { fail } } - stream::client::send(bc, ~"abc"); + stream::client::send(move bc, ~"abc"); error!("done with first select2"); let (ac, ap) = stream::init(); let (bc, bp) = stream::init(); - stream::client::send(bc, ~"abc"); + stream::client::send(move bc, ~"abc"); - match pipes::select2(ap, bp) { + match pipes::select2(move ap, move bp) { either::Left(*) => { fail } either::Right(*) => { } } - stream::client::send(ac, 42); + stream::client::send(move ac, 42); } diff --git a/src/test/run-pass/pipe-sleep.rs b/src/test/run-pass/pipe-sleep.rs index 4e901c69d29d..c9975bec9469 100644 --- a/src/test/run-pass/pipe-sleep.rs +++ b/src/test/run-pass/pipe-sleep.rs @@ -14,10 +14,10 @@ proto! oneshot ( fn main() { use oneshot::client::*; - let c = pipes::spawn_service(oneshot::init, |p| { recv(p); }); + let c = pipes::spawn_service(oneshot::init, |p| { recv(move p); }); let iotask = uv::global_loop::get(); sleep(iotask, 500); - signal(c); + signal(move c); } \ No newline at end of file diff --git a/src/test/run-pass/regions-copy-closure.rs b/src/test/run-pass/regions-copy-closure.rs index 2e03c5f82c45..834272ca920e 100644 --- a/src/test/run-pass/regions-copy-closure.rs +++ b/src/test/run-pass/regions-copy-closure.rs @@ -2,8 +2,8 @@ struct closure_box { cl: &fn(), } -fn box_it(x: &r/fn()) -> closure_box/&r { - closure_box {cl: x} +fn box_it(+x: &r/fn()) -> closure_box/&r { + closure_box {cl: move x} } fn main() { diff --git a/src/test/run-pass/regions-static-closure.rs b/src/test/run-pass/regions-static-closure.rs index 61e04c4e7769..6622a6aa5697 100644 --- a/src/test/run-pass/regions-static-closure.rs +++ b/src/test/run-pass/regions-static-closure.rs @@ -2,8 +2,8 @@ struct closure_box { cl: &fn(), } -fn box_it(x: &r/fn()) -> closure_box/&r { - closure_box {cl: x} +fn box_it(+x: &r/fn()) -> closure_box/&r { + closure_box {cl: move x} } fn call_static_closure(cl: closure_box/&static) { @@ -12,5 +12,5 @@ fn call_static_closure(cl: closure_box/&static) { fn main() { let cl_box = box_it(|| debug!("Hello, world!")); - call_static_closure(cl_box); + call_static_closure(move cl_box); } diff --git a/src/test/run-pass/resource-assign-is-not-copy.rs b/src/test/run-pass/resource-assign-is-not-copy.rs index 7f3bc016a6ad..f0bea875df90 100644 --- a/src/test/run-pass/resource-assign-is-not-copy.rs +++ b/src/test/run-pass/resource-assign-is-not-copy.rs @@ -14,8 +14,8 @@ fn main() { // Even though these look like copies, they are guaranteed not to be { let a = r(i); - let b = (a, 10); - let (c, _d) = b; + let b = (move a, 10); + let (c, _d) = move b; log(debug, c); } assert *i == 1; diff --git a/src/test/run-pass/resource-cycle.rs b/src/test/run-pass/resource-cycle.rs index 26e19ee1b0c6..893042842d09 100644 --- a/src/test/run-pass/resource-cycle.rs +++ b/src/test/run-pass/resource-cycle.rs @@ -24,10 +24,10 @@ enum t = { fn main() unsafe { let i1 = ~0; let i1p = cast::reinterpret_cast(&i1); - cast::forget(i1); + cast::forget(move i1); let i2 = ~0; let i2p = cast::reinterpret_cast(&i2); - cast::forget(i2); + cast::forget(move i2); let x1 = @t({ mut next: None, @@ -35,7 +35,7 @@ fn main() unsafe { let rs = r(i1p); debug!("r = %x", cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); - rs } + move rs } }); debug!("x1 = %x, x1.r = %x", @@ -48,7 +48,7 @@ fn main() unsafe { let rs = r(i2p); debug!("r2 = %x", cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); - rs + move rs } }); diff --git a/src/test/run-pass/resource-cycle2.rs b/src/test/run-pass/resource-cycle2.rs index b522808c4947..a38950e17e36 100644 --- a/src/test/run-pass/resource-cycle2.rs +++ b/src/test/run-pass/resource-cycle2.rs @@ -27,10 +27,10 @@ enum t = { fn main() unsafe { let i1 = ~0xA; let i1p = cast::reinterpret_cast(&i1); - cast::forget(i1); + cast::forget(move i1); let i2 = ~0xA; let i2p = cast::reinterpret_cast(&i2); - cast::forget(i2); + cast::forget(move i2); let u1 = {a: 0xB, b: 0xC, c: i1p}; let u2 = {a: 0xB, b: 0xC, c: i2p}; diff --git a/src/test/run-pass/resource-cycle3.rs b/src/test/run-pass/resource-cycle3.rs index efb1915799c3..aa0f18089d9e 100644 --- a/src/test/run-pass/resource-cycle3.rs +++ b/src/test/run-pass/resource-cycle3.rs @@ -34,10 +34,10 @@ enum t = { fn main() unsafe { let i1 = ~0xA; let i1p = cast::reinterpret_cast(&i1); - cast::forget(i1); + cast::forget(move i1); let i2 = ~0xA; let i2p = cast::reinterpret_cast(&i2); - cast::forget(i2); + cast::forget(move i2); let u1 = {a: 0xB, b: 0xC, c: i1p}; let u2 = {a: 0xB, b: 0xC, c: i2p}; diff --git a/src/test/run-pass/rt-sched-1.rs b/src/test/run-pass/rt-sched-1.rs index 690d93172ebc..976225c0e239 100644 --- a/src/test/run-pass/rt-sched-1.rs +++ b/src/test/run-pass/rt-sched-1.rs @@ -35,6 +35,6 @@ fn main() unsafe { }; let fptr = cast::reinterpret_cast(&ptr::addr_of(&f)); rustrt::start_task(new_task_id, fptr); - cast::forget(f); + cast::forget(move f); comm::recv(po); } diff --git a/src/test/run-pass/select-macro.rs b/src/test/run-pass/select-macro.rs index 517c61266d9c..d6ce85ac3446 100644 --- a/src/test/run-pass/select-macro.rs +++ b/src/test/run-pass/select-macro.rs @@ -17,18 +17,18 @@ macro_rules! select_if ( $count:expr, $port:path => [ $(type_this $message:path$(($(x $x: ident),+))dont_type_this* - -> $next:ident => { $e:expr }),+ + -> $next:ident => { move $e:expr }),+ ] $(, $ports:path => [ $(type_this $messages:path$(($(x $xs: ident),+))dont_type_this* - -> $nexts:ident => { $es:expr }),+ + -> $nexts:ident => { move $es:expr }),+ ] )* } => { if $index == $count { match move pipes::try_recv($port) { $(Some($message($($(move $x,)+)* move next)) => { - let $next = next; - $e + let $next = move next; + move $e })+ _ => fail } @@ -38,7 +38,7 @@ macro_rules! select_if ( $count + 1 $(, $ports => [ $(type_this $messages$(($(x $xs),+))dont_type_this* - -> $nexts => { $es }),+ + -> $nexts => { move $es }),+ ])* ) } @@ -54,7 +54,7 @@ macro_rules! select ( } => { let index = pipes::selecti([$(($port).header()),+]/_); select_if!(index, 0 $(, $port => [ - $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { $e }),+ + $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { move $e }),+ ])+) } ) diff --git a/src/test/run-pass/static-method-test.rs b/src/test/run-pass/static-method-test.rs index 57d6558dd773..6ce4ff348155 100644 --- a/src/test/run-pass/static-method-test.rs +++ b/src/test/run-pass/static-method-test.rs @@ -13,13 +13,13 @@ fn andand(x1: T, x2: T) -> T { impl bool: bool_like { static fn select(&&b: bool, +x1: A, +x2: A) -> A { - if b { x1 } else { x2 } + if b { move x1 } else { move x2 } } } impl int: bool_like { static fn select(&&b: int, +x1: A, +x2: A) -> A { - if b != 0 { x1 } else { x2 } + if b != 0 { move x1 } else { move x2 } } } diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs index d8586e7ef39c..1244af227f4a 100644 --- a/src/test/run-pass/task-comm-0.rs +++ b/src/test/run-pass/task-comm-0.rs @@ -19,7 +19,7 @@ fn test05_start(ch : Chan) { fn test05() { let (ch, po) = pipes::stream(); - task::spawn(|| test05_start(ch) ); + task::spawn(|move ch| test05_start(ch) ); let mut value = po.recv(); log(error, value); value = po.recv(); diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index 0c69f414cc81..55fff5422e3a 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -5,7 +5,7 @@ extern mod std; fn start(c: pipes::Chan>) { let (ch, p) = pipes::stream(); - c.send(ch); + c.send(move ch); let mut a; let mut b; @@ -14,12 +14,12 @@ fn start(c: pipes::Chan>) { log(error, a); b = p.recv(); assert b == ~"B"; - log(error, b); + log(error, move b); } fn main() { let (ch, p) = pipes::stream(); - let child = task::spawn(|| start(ch) ); + let child = task::spawn(|move ch| start(ch) ); let c = p.recv(); c.send(~"A"); diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs index c660ecd3a92f..86fb20ad8180 100644 --- a/src/test/run-pass/task-comm-11.rs +++ b/src/test/run-pass/task-comm-11.rs @@ -5,11 +5,11 @@ extern mod std; fn start(c: pipes::Chan>) { let (ch, p) = pipes::stream(); - c.send(ch); + c.send(move ch); } fn main() { let (ch, p) = pipes::stream(); - let child = task::spawn(|| start(ch) ); + let child = task::spawn(|move ch| start(ch) ); let c = p.recv(); } diff --git a/src/test/run-pass/task-comm-12.rs b/src/test/run-pass/task-comm-12.rs index c0f97c85bce2..64ea3fb9d0e5 100644 --- a/src/test/run-pass/task-comm-12.rs +++ b/src/test/run-pass/task-comm-12.rs @@ -7,7 +7,7 @@ fn start(&&task_number: int) { debug!("Started / Finished task."); } fn test00() { let i: int = 0; let mut result = None; - do task::task().future_result(|+r| { result = Some(r); }).spawn { + do task::task().future_result(|+r| { result = Some(move r); }).spawn { start(i) } @@ -19,7 +19,7 @@ fn test00() { } // Try joining tasks that have already finished. - future::get(&option::unwrap(result)); + future::get(&option::unwrap(move result)); debug!("Joined task."); } diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs index 7302bcdaa94d..9827b3c36b92 100644 --- a/src/test/run-pass/task-comm-13.rs +++ b/src/test/run-pass/task-comm-13.rs @@ -12,6 +12,6 @@ fn start(c: pipes::Chan, start: int, number_of_messages: int) { fn main() { debug!("Check that we don't deadlock."); let (ch, p) = pipes::stream(); - task::try(|| start(ch, 0, 10) ); + task::try(|move ch| start(ch, 0, 10) ); debug!("Joined task"); } diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index 14f8e3bfa2be..7f63d22be47a 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -9,8 +9,8 @@ fn main() { while (i > 0) { log(debug, i); let (ch, p) = pipes::stream(); - po.add(p); - task::spawn(|copy i| child(i, ch) ); + po.add(move p); + task::spawn(|move ch, copy i| child(i, ch) ); i = i - 1; } diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index 98b095426eab..c3734cb5d9c6 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -18,6 +18,6 @@ fn main() { // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! let (ch, p) = pipes::stream(); - task::spawn(|| start(ch, 10)); + task::spawn(|move ch| start(ch, 10)); p.recv(); } diff --git a/src/test/run-pass/task-comm-16.rs b/src/test/run-pass/task-comm-16.rs index a69b7b0c15bc..47bc99b53f4d 100644 --- a/src/test/run-pass/task-comm-16.rs +++ b/src/test/run-pass/task-comm-16.rs @@ -91,7 +91,7 @@ fn test_tag() { fn test_chan() { let (ch, po) = pipes::stream(); let (ch0, po0) = pipes::stream(); - ch.send(ch0); + ch.send(move ch0); let ch1 = po.recv(); // Does the transmitted channel still work? diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index 4faac4fdac19..7082cd55ac83 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -34,8 +34,8 @@ fn test00() { while i < number_of_tasks { let ch = po.chan(); do task::task().future_result(|+r| { - results.push(r); - }).spawn |copy i| { + results.push(move r); + }).spawn |move ch, copy i| { test00_start(ch, i, number_of_messages) } i = i + 1; diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index d4cba9f71abe..c34dfb319d82 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -17,19 +17,19 @@ fn test00() { let number_of_messages: int = 10; let c = p.chan(); - do task::spawn { + do task::spawn |move c| { test00_start(c, number_of_messages * 0, number_of_messages); } let c = p.chan(); - do task::spawn { + do task::spawn |move c| { test00_start(c, number_of_messages * 1, number_of_messages); } let c = p.chan(); - do task::spawn { + do task::spawn |move c| { test00_start(c, number_of_messages * 2, number_of_messages); } let c = p.chan(); - do task::spawn { + do task::spawn |move c| { test00_start(c, number_of_messages * 3, number_of_messages); } diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index c159b7b77e50..5ed5899658d2 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -18,7 +18,8 @@ fn test00() { let ch = p.chan(); let mut result = None; - do task::task().future_result(|+r| { result = Some(r); }).spawn { + do task::task().future_result(|+r| { result = Some(move r); }).spawn + |move ch| { test00_start(ch, number_of_messages); } @@ -29,7 +30,7 @@ fn test00() { i += 1; } - future::get(&option::unwrap(result)); + future::get(&option::unwrap(move result)); assert (sum == number_of_messages * (number_of_messages - 1) / 2); } diff --git a/src/test/run-pass/task-comm.rs b/src/test/run-pass/task-comm.rs index c88b556fd53f..aba0bd660052 100644 --- a/src/test/run-pass/task-comm.rs +++ b/src/test/run-pass/task-comm.rs @@ -40,7 +40,7 @@ fn test00() { while i < number_of_tasks { i = i + 1; do task::task().future_result(|+r| { - results.push(r); + results.push(move r); }).spawn |copy i| { test00_start(ch, i, number_of_messages); } @@ -127,7 +127,7 @@ fn test06() { while i < number_of_tasks { i = i + 1; do task::task().future_result(|+r| { - results.push(r); + results.push(move r); }).spawn |copy i| { test06_start(i); }; diff --git a/src/test/run-pass/trait-to-str.rs b/src/test/run-pass/trait-to-str.rs index 14ca4df66a0f..2dfe48c49511 100644 --- a/src/test/run-pass/trait-to-str.rs +++ b/src/test/run-pass/trait-to-str.rs @@ -30,7 +30,7 @@ fn main() { assert indirect(~[10, 20]) == ~"[10, 20]!"; fn indirect2(x: T) -> ~str { - indirect(x) + indirect(move x) } assert indirect2(~[1]) == ~"[1]!"; } diff --git a/src/test/run-pass/unique-fn-arg-move.rs b/src/test/run-pass/unique-fn-arg-move.rs index 2126e3292479..3e162e13d78a 100644 --- a/src/test/run-pass/unique-fn-arg-move.rs +++ b/src/test/run-pass/unique-fn-arg-move.rs @@ -4,5 +4,5 @@ fn f(-i: ~int) { fn main() { let i = ~100; - f(i); + f(move i); } \ No newline at end of file diff --git a/src/test/run-pass/yield.rs b/src/test/run-pass/yield.rs index f9c2ad2547d6..11208a969db2 100644 --- a/src/test/run-pass/yield.rs +++ b/src/test/run-pass/yield.rs @@ -4,13 +4,13 @@ use task::*; fn main() { let mut result = None; - task::task().future_result(|+r| { result = Some(r); }).spawn(child); + task::task().future_result(|+r| { result = Some(move r); }).spawn(child); error!("1"); yield(); error!("2"); yield(); error!("3"); - future::get(&option::unwrap(result)); + future::get(&option::unwrap(move result)); } fn child() { diff --git a/src/test/run-pass/yield1.rs b/src/test/run-pass/yield1.rs index 05c5e833babf..ec77a6863245 100644 --- a/src/test/run-pass/yield1.rs +++ b/src/test/run-pass/yield1.rs @@ -4,10 +4,10 @@ use task::*; fn main() { let mut result = None; - task::task().future_result(|+r| { result = Some(r); }).spawn(child); + task::task().future_result(|+r| { result = Some(move r); }).spawn(child); error!("1"); yield(); - future::get(&option::unwrap(result)); + future::get(&option::unwrap(move result)); } fn child() { error!("2"); } From 71dbbe145c42f3d9dc7842861738bfa64550dbbd Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:55:21 -0700 Subject: [PATCH 189/292] Make moves explicit in rfail tests --- src/test/run-fail/port-type.rs | 2 +- src/test/run-fail/unwind-box-res.rs | 2 +- src/test/run-fail/unwind-move.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/run-fail/port-type.rs b/src/test/run-fail/port-type.rs index 30714413c537..9f2974d2cc27 100644 --- a/src/test/run-fail/port-type.rs +++ b/src/test/run-fail/port-type.rs @@ -12,7 +12,7 @@ fn echo(c: Chan, oc: Chan>) { send(oc, Chan(&p)); let x = recv(p); - send(c, x); + send(c, move x); } fn main() { fail ~"meep"; } diff --git a/src/test/run-fail/unwind-box-res.rs b/src/test/run-fail/unwind-box-res.rs index 0bea0f934f40..ca85aa970173 100644 --- a/src/test/run-fail/unwind-box-res.rs +++ b/src/test/run-fail/unwind-box-res.rs @@ -20,7 +20,7 @@ fn r(v: *int) -> r { fn main() unsafe { let i1 = ~0; let i1p = cast::reinterpret_cast(&i1); - cast::forget(i1); + cast::forget(move i1); let x = @r(i1p); failfn(); log(error, x); diff --git a/src/test/run-fail/unwind-move.rs b/src/test/run-fail/unwind-move.rs index 311cb52b1345..995edbcc05ba 100644 --- a/src/test/run-fail/unwind-move.rs +++ b/src/test/run-fail/unwind-move.rs @@ -1,9 +1,9 @@ // error-pattern:fail -fn f(-a: @int) { +fn f(-_a: @int) { fail; } fn main() { let a = @0; - f(a); + f(move a); } \ No newline at end of file From 632d60691a8bd9fb85e3874016d4c1b24657de03 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 12 Oct 2012 17:57:06 -0700 Subject: [PATCH 190/292] Test that functional struct update exprs get rejected if... ...they require copying noncopyable fields. --- .../compile-fail/functional-struct-update.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/test/compile-fail/functional-struct-update.rs diff --git a/src/test/compile-fail/functional-struct-update.rs b/src/test/compile-fail/functional-struct-update.rs new file mode 100644 index 000000000000..8d7913a62faa --- /dev/null +++ b/src/test/compile-fail/functional-struct-update.rs @@ -0,0 +1,16 @@ +struct Bar { + x: int, + drop { io::println("Goodbye, cruel world"); } +} + +struct Foo { + x: int, + y: Bar +} + +fn main() { + let a = Foo { x: 1, y: Bar { x: 5 } }; + let c = Foo { x: 4, .. a}; //~ ERROR copying a noncopyable value + io::println(fmt!("%?", c)); +} + From 9abc7f0a1cb5086fa6d9a38841258859a16cbdfe Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 5 Sep 2012 19:19:37 -0700 Subject: [PATCH 191/292] (For legacy code:) In liveness, require that by-move arguments are rvalues --- src/rustc/middle/liveness.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 5ead871a661f..a0a422bc027b 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -1461,7 +1461,15 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) { match ty::resolved_mode(self.tcx, arg_ty.mode) { by_val | by_copy | by_ref => {} by_move => { - self.check_move_from_expr(*arg_expr, vt); + if ty::expr_is_lval(self.tcx, self.ir.method_map, + *arg_expr) { + // Probably a bad error message (what's an rvalue?) + // but I can't think of anything better + self.tcx.sess.span_err(arg_expr.span, + #fmt("Move mode argument must be an rvalue: try \ + (move %s) instead", expr_to_str(*arg_expr, + self.tcx.sess.intr()))); + } } } } From c4155f5ea37b9921eff310d9ca06402d0bb9b0f6 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:54:08 -0700 Subject: [PATCH 192/292] Change the kind checker to ignore results of last-use and require explicit moves. Also provide more info in some error messages. Also: check that non-copyable struct fields don't get copied. Closes #3481 --- src/rustc/middle/kind.rs | 86 +++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index 7b473cedb4c5..edd3c6453586 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -89,8 +89,11 @@ fn check_crate(tcx: ty::ctxt, tcx.sess.abort_if_errors(); } +// bool flag is only used for checking closures, +// where it refers to whether a var is 'move' in the +// capture clause type check_fn = fn@(ctx, node_id, Option<@freevar_entry>, - bool, ty::t, sp: span); + bool, ty::t, sp: span); // Yields the appropriate function to check the kind of closed over // variables. `id` is the node_id for some expression that creates the @@ -111,7 +114,6 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { "to copy values into a ~fn closure, use a \ capture clause: `fn~(copy x)` or `|copy x|`"))); } - // check that only immutable variables are implicitly copied in for fv.each |fv| { check_imm_free_var(cx, fv.def, fv.span); @@ -132,7 +134,6 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { "to copy values into a @fn closure, use a \ capture clause: `fn~(copy x)` or `|copy x|`"))); } - // check that only immutable variables are implicitly copied in for fv.each |fv| { check_imm_free_var(cx, fv.def, fv.span); @@ -151,7 +152,7 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { } fn check_for_bare(cx: ctx, _id: node_id, _fv: Option<@freevar_entry>, - _is_move: bool,_var_t: ty::t, sp: span) { + _is_move: bool, _var_t: ty::t, sp: span) { cx.tcx.sess.span_err(sp, ~"attempted dynamic environment capture"); } @@ -189,6 +190,7 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, let cap_def = cx.tcx.def_map.get(cap_item.id); let cap_def_id = ast_util::def_id_of_def(cap_def).node; let ty = ty::node_id_to_type(cx.tcx, cap_def_id); + // Here's where is_move isn't always false... chk(cx, fn_id, None, cap_item.is_move, ty, cap_item.span); cap_def_id }; @@ -201,17 +203,10 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, // skip over free variables that appear in the cap clause if captured_vars.contains(&id) { loop; } - // if this is the last use of the variable, then it will be - // a move and not a copy - let is_move = { - match cx.last_use_map.find(fn_id) { - Some(vars) => (*vars).contains(&id), - None => false - } - }; - let ty = ty::node_id_to_type(cx.tcx, id); - chk(cx, fn_id, Some(*fv), is_move, ty, fv.span); + // is_move is always false here. See the let captured_vars... + // code above for where it's not always false. + chk(cx, fn_id, Some(*fv), false, ty, fv.span); } } @@ -220,7 +215,9 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, fn check_block(b: blk, cx: ctx, v: visit::vt) { match b.node.expr { - Some(ex) => maybe_copy(cx, ex, None), + Some(ex) => maybe_copy(cx, ex, + Some(("Tail expressions in blocks must be copyable", + "(Try adding a move)"))), _ => () } visit::visit_block(b, cx, v); @@ -281,33 +278,45 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { expr_assign(_, ex) | expr_unary(box(_), ex) | expr_unary(uniq(_), ex) | expr_ret(Some(ex)) => { - maybe_copy(cx, ex, None); + maybe_copy(cx, ex, Some(("Returned values must be copyable", + "Try adding a move"))); } expr_cast(source, _) => { - maybe_copy(cx, source, None); + maybe_copy(cx, source, Some(("Casted values must be copyable", + "Try adding a move"))); check_cast_for_escaping_regions(cx, source, e); } - expr_copy(expr) => check_copy_ex(cx, expr, false, None), + expr_copy(expr) => check_copy_ex(cx, expr, false, + Some(("Explicit copy requires a copyable argument", ""))), // Vector add copies, but not "implicitly" - expr_assign_op(_, _, ex) => check_copy_ex(cx, ex, false, None), + expr_assign_op(_, _, ex) => check_copy_ex(cx, ex, false, + Some(("Assignment with operation requires \ + a copyable argument", ""))), expr_binary(add, ls, rs) => { - check_copy_ex(cx, ls, false, None); - check_copy_ex(cx, rs, false, None); + let reason = Some(("Binary operators require copyable arguments", + "")); + check_copy_ex(cx, ls, false, reason); + check_copy_ex(cx, rs, false, reason); } - expr_rec(fields, def) => { - for fields.each |field| { maybe_copy(cx, field.node.expr, None); } + expr_rec(fields, def) | expr_struct(_, fields, def) => { + for fields.each |field| { maybe_copy(cx, field.node.expr, + Some(("Record or struct fields require \ + copyable arguments", ""))); } match def { Some(ex) => { // All noncopyable fields must be overridden let t = ty::expr_ty(cx.tcx, ex); let ty_fields = match ty::get(t).sty { ty::ty_rec(f) => f, - _ => cx.tcx.sess.span_bug(ex.span, ~"bad expr type in record") + ty::ty_class(did, substs) => + ty::class_items_as_fields(cx.tcx, did, &substs), + _ => cx.tcx.sess.span_bug(ex.span, + ~"bad base expr type in record") }; for ty_fields.each |tf| { if !vec::any(fields, |f| f.node.ident == tf.ident ) && !ty::kind_can_be_copied(ty::type_kind(cx.tcx, tf.mt.ty)) { - cx.tcx.sess.span_err(ex.span, + cx.tcx.sess.span_err(e.span, ~"copying a noncopyable value"); } } @@ -316,16 +325,16 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { } } expr_tup(exprs) | expr_vec(exprs, _) => { - for exprs.each |expr| { maybe_copy(cx, *expr, None); } + for exprs.each |expr| { maybe_copy(cx, *expr, + Some(("Tuple or vec elements must be copyable", ""))); } } expr_call(f, args, _) => { - let mut i = 0u; - for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).each |arg_t| { + for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).eachi |i, arg_t| { match ty::arg_mode(cx.tcx, *arg_t) { - by_copy => maybe_copy(cx, args[i], None), + by_copy => maybe_copy(cx, args[i], + Some(("Callee takes its argument by copy", ""))), by_ref | by_val | by_move => () } - i += 1u; } } expr_field(lhs, _, _) => { @@ -334,7 +343,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { match cx.method_map.find(e.id) { Some(ref mme) => { match ty::arg_mode(cx.tcx, mme.self_arg) { - by_copy => maybe_copy(cx, lhs, None), + by_copy => maybe_copy(cx, lhs, + Some(("Method call takes its self argument by copy", + ""))), by_ref | by_val | by_move => () } } @@ -344,10 +355,12 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { expr_repeat(element, count_expr, _) => { let count = ty::eval_repeat_count(cx.tcx, count_expr, e.span); if count == 1 { - maybe_copy(cx, element, None); + maybe_copy(cx, element, Some(("Trivial repeat takes its element \ + by copy", ""))); } else { let element_ty = ty::expr_ty(cx.tcx, element); - check_copy(cx, element.id, element_ty, element.span, true, None); + check_copy(cx, element.id, element_ty, element.span, true, + Some(("Repeat takes its elements by copy", ""))); } } _ => { } @@ -360,7 +373,9 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt) { stmt_decl(@{node: decl_local(locals), _}, _) => { for locals.each |local| { match local.node.init { - Some({op: init_assign, expr}) => maybe_copy(cx, expr, None), + Some({op: init_assign, expr}) => + maybe_copy(cx, expr, Some(("Initializer statement \ + takes its right-hand side by copy", ""))), _ => {} } } @@ -434,9 +449,6 @@ fn check_copy_ex(cx: ctx, ex: @expr, implicit_copy: bool, why: Option<(&str,&str)>) { if ty::expr_is_lval(cx.tcx, cx.method_map, ex) && - // this is a move - !cx.last_use_map.contains_key(ex.id) && - // a reference to a constant like `none`... no need to warn // about *this* even if the type is Option<~int> !is_nullary_variant(cx, ex) && From c6780fbb0c62819b2b1851c08a2c08fb3f1c9695 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 18 Sep 2012 22:54:57 -0700 Subject: [PATCH 193/292] Make trans ignore last use --- src/rustc/middle/trans/closure.rs | 5 ++--- src/rustc/middle/trans/expr.rs | 21 +++++++-------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 1ab25a183293..655efe75bf65 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -244,7 +244,6 @@ fn store_environment(bcx: block, fn build_closure(bcx0: block, cap_vars: ~[capture::capture_var], ck: ty::closure_kind, - id: ast::node_id, include_ret_handle: Option) -> closure_result { let _icx = bcx0.insn_ctxt("closure::build_closure"); // If we need to, package up the iterator body to call @@ -255,7 +254,7 @@ fn build_closure(bcx0: block, let mut env_vals = ~[]; for vec::each(cap_vars) |cap_var| { debug!("Building closure: captured variable %?", *cap_var); - let datum = expr::trans_local_var(bcx, id, cap_var.def); + let datum = expr::trans_local_var(bcx, cap_var.def); match cap_var.mode { capture::cap_ref => { assert ck == ty::ck_block; @@ -370,7 +369,7 @@ fn trans_expr_fn(bcx: block, let cap_vars = capture::compute_capture_vars(ccx.tcx, id, proto, cap_clause); let ret_handle = match is_loop_body { Some(x) => x, None => None }; - let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, id, + let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, ret_handle); trans_closure(ccx, sub_path, decl, body, llfn, no_self, bcx.fcx.param_substs, id, |fcx| { diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index c841d9bd9137..333d76a91ee6 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -748,13 +748,13 @@ fn trans_def_lvalue(bcx: block, ref_expr: @ast::expr, _ => { DatumBlock { bcx: bcx, - datum: trans_local_var(bcx, ref_expr.id, def) + datum: trans_local_var(bcx, def) } } } } -fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { +fn trans_local_var(bcx: block, def: ast::def) -> Datum { let _icx = bcx.insn_ctxt("trans_local_var"); return match def { @@ -776,10 +776,10 @@ fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { } } ast::def_arg(nid, _) => { - take_local(bcx, ref_id, bcx.fcx.llargs, nid) + take_local(bcx, bcx.fcx.llargs, nid) } ast::def_local(nid, _) | ast::def_binding(nid, _) => { - take_local(bcx, ref_id, bcx.fcx.lllocals, nid) + take_local(bcx, bcx.fcx.lllocals, nid) } ast::def_self(nid) => { let self_info: ValSelfData = match bcx.fcx.llself { @@ -809,15 +809,8 @@ fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { }; fn take_local(bcx: block, - ref_id: ast::node_id, table: HashMap, nid: ast::node_id) -> Datum { - let is_last_use = match bcx.ccx().maps.last_use_map.find(ref_id) { - None => false, - Some(vars) => (*vars).contains(&nid) - }; - - let source = if is_last_use {FromLastUseLvalue} else {FromLvalue}; let (v, mode) = match table.find(nid) { Some(local_mem(v)) => (v, ByRef), @@ -829,10 +822,10 @@ fn trans_local_var(bcx: block, ref_id: ast::node_id, def: ast::def) -> Datum { }; let ty = node_id_type(bcx, nid); - debug!("take_local(nid=%?, last_use=%b, v=%s, mode=%?, ty=%s)", - nid, is_last_use, bcx.val_str(v), mode, bcx.ty_to_str(ty)); + debug!("take_local(nid=%?, v=%s, mode=%?, ty=%s)", + nid, bcx.val_str(v), mode, bcx.ty_to_str(ty)); - Datum { val: v, ty: ty, mode: mode, source: source } + Datum { val: v, ty: ty, mode: mode, source: FromLvalue } } } From f1e5b36ab25a6a6c64dac21868cb8f9550c87901 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 12 Oct 2012 20:59:44 -0700 Subject: [PATCH 194/292] Remove unneeded parens --- src/rustc/middle/kind.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index edd3c6453586..b3ca3dc047d5 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -217,7 +217,7 @@ fn check_block(b: blk, cx: ctx, v: visit::vt) { match b.node.expr { Some(ex) => maybe_copy(cx, ex, Some(("Tail expressions in blocks must be copyable", - "(Try adding a move)"))), + "Try adding a move"))), _ => () } visit::visit_block(b, cx, v); From 9406f8101dd32b4458b8c042a1bfb1bb150a2276 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 12 Oct 2012 22:15:13 -0700 Subject: [PATCH 195/292] Avoid repeating 'try adding a move' hint --- src/rustc/middle/kind.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index b3ca3dc047d5..36a05d665061 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -38,6 +38,8 @@ use lint::{non_implicitly_copyable_typarams,implicit_copies}; // primitives in the stdlib are explicitly annotated to only take sendable // types. +const try_adding: &str = "Try adding a move"; + fn kind_to_str(k: kind) -> ~str { let mut kinds = ~[]; @@ -217,7 +219,7 @@ fn check_block(b: blk, cx: ctx, v: visit::vt) { match b.node.expr { Some(ex) => maybe_copy(cx, ex, Some(("Tail expressions in blocks must be copyable", - "Try adding a move"))), + try_adding))), _ => () } visit::visit_block(b, cx, v); @@ -279,11 +281,11 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { expr_unary(box(_), ex) | expr_unary(uniq(_), ex) | expr_ret(Some(ex)) => { maybe_copy(cx, ex, Some(("Returned values must be copyable", - "Try adding a move"))); + try_adding))); } expr_cast(source, _) => { maybe_copy(cx, source, Some(("Casted values must be copyable", - "Try adding a move"))); + try_adding))); check_cast_for_escaping_regions(cx, source, e); } expr_copy(expr) => check_copy_ex(cx, expr, false, From e9caa3fe2e291b7f2cea624bfd0dc879e95fe382 Mon Sep 17 00:00:00 2001 From: Gareth Daniel Smith Date: Thu, 4 Oct 2012 20:22:53 +0100 Subject: [PATCH 196/292] Add an &str.to_managed method to allow creating non-constant @str values (for issue #3433). --- src/libcore/str.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 677a33d56c0d..e2e7b15b1d78 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1869,6 +1869,11 @@ pub pure fn escape_unicode(s: &str) -> ~str { move out } +extern mod rustrt { + #[rust_stack] + pure fn upcall_str_new_shared(cstr: *libc::c_char, len: size_t) -> @str; +} + /// Unsafe operations pub mod raw { @@ -2090,6 +2095,7 @@ pub trait StrSlice { pure fn trim_left() -> ~str; pure fn trim_right() -> ~str; pure fn to_unique() -> ~str; + pure fn to_managed() -> @str; pure fn char_at(i: uint) -> char; } @@ -2213,6 +2219,14 @@ impl &str: StrSlice { #[inline] pure fn to_unique() -> ~str { self.slice(0, self.len()) } + #[inline] + pure fn to_managed() -> @str { + do str::as_buf(self) |p, _len| { + rustrt::upcall_str_new_shared(p as *libc::c_char, + self.len() as size_t) + } + } + #[inline] pure fn char_at(i: uint) -> char { char_at(self, i) } } @@ -3190,4 +3204,10 @@ mod tests { assert escape_default(~"\U0001d4ea\r") == ~"\\U0001d4ea\\r"; } + #[test] + fn test_to_managed() { + assert (~"abc").to_managed() == @"abc"; + assert view("abcdef", 1, 5).to_managed() == @"bcde"; + } + } From 07edf9036715bde27cc7bbc0feb3ee6e461130da Mon Sep 17 00:00:00 2001 From: Gareth Daniel Smith Date: Sat, 6 Oct 2012 11:11:06 +0100 Subject: [PATCH 197/292] Implement to_managed without using an upcall function, as suggested by brson. --- src/libcore/str.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index e2e7b15b1d78..447cb59acf80 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1869,11 +1869,6 @@ pub pure fn escape_unicode(s: &str) -> ~str { move out } -extern mod rustrt { - #[rust_stack] - pure fn upcall_str_new_shared(cstr: *libc::c_char, len: size_t) -> @str; -} - /// Unsafe operations pub mod raw { @@ -2221,10 +2216,10 @@ impl &str: StrSlice { #[inline] pure fn to_managed() -> @str { - do str::as_buf(self) |p, _len| { - rustrt::upcall_str_new_shared(p as *libc::c_char, - self.len() as size_t) - } + let v = at_vec::from_fn(self.len() + 1, |i| { + if i == self.len() { 0 } else { self[i] } + }); + unsafe { ::cast::transmute(v) } } #[inline] From 01aaeef619cc249a6c4555b3c865bb081e5b80c5 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Sun, 14 Oct 2012 14:45:21 +0200 Subject: [PATCH 198/292] Use gpgv for signature verification in cargo Parsing gpg output for signature verification is not recommended, as it can break easily (and doesn't work with i18n). This patch makes use of gpgv, as suggested by gpg authors: http://lists.gnupg.org/pipermail/gnupg-users/2004-August/023141.html This closes #3762. Signed-off-by: Luca Bruno --- src/cargo/cargo.rs | 37 ++++++++++++++++++------------------- src/cargo/pgp.rs | 23 +++++++++++------------ 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index 5f39eb6b960e..322d78004208 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -1162,20 +1162,20 @@ fn sync_one_file(c: &Cargo, dir: &Path, src: @Source) -> bool { } match (src.key, src.keyfp) { (Some(_), Some(f)) => { - let r = pgp::verify(&c.root, &pkgfile, &sigfile, f); + let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s with key %s", + name, f)); return false; } if has_src_file { - let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f); + let e = pgp::verify(&c.root, &srcfile, &srcsigfile); if !e { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s with key %s", + name, f)); return false; } } @@ -1273,21 +1273,21 @@ fn sync_one_git(c: &Cargo, dir: &Path, src: @Source) -> bool { } match (src.key, src.keyfp) { (Some(_), Some(f)) => { - let r = pgp::verify(&c.root, &pkgfile, &sigfile, f); + let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s with key %s", + name, f)); rollback(name, dir, false); return false; } if has_src_file { - let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f); + let e = pgp::verify(&c.root, &srcfile, &srcsigfile); if !e { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s with key %s", + name, f)); rollback(name, dir, false); return false; } @@ -1370,11 +1370,11 @@ fn sync_one_curl(c: &Cargo, dir: &Path, src: @Source) -> bool { return false; } - let r = pgp::verify(&c.root, &pkgfile, &sigfile, f); + let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s", - name)); + error(fmt!("signature verification failed for source %s with key %s", + name, f)); return false; } @@ -1390,11 +1390,11 @@ fn sync_one_curl(c: &Cargo, dir: &Path, src: @Source) -> bool { return false; } - let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f); + let e = pgp::verify(&c.root, &srcfile, &srcsigfile); if !e { error(~"signature verification failed for " + - ~"source " + name); + ~"source " + name + ~" with key " + f); return false; } } @@ -1463,8 +1463,7 @@ fn cmd_init(c: &Cargo) { return; } - let r = pgp::verify(&c.root, &srcfile, &sigfile, - pgp::signing_key_fp()); + let r = pgp::verify(&c.root, &srcfile, &sigfile); if !r { error(fmt!("signature verification failed for '%s'", srcfile.to_str())); diff --git a/src/cargo/pgp.rs b/src/cargo/pgp.rs index 17cb8dc64878..5fbfa55838c8 100644 --- a/src/cargo/pgp.rs +++ b/src/cargo/pgp.rs @@ -1,5 +1,5 @@ -fn gpg(args: ~[~str]) -> { status: int, out: ~str, err: ~str } { - return run::program_output(~"gpg", args); +fn gpgv(args: ~[~str]) -> { status: int, out: ~str, err: ~str } { + return run::program_output(~"gpgv", args); } fn signing_key() -> ~str { @@ -59,7 +59,7 @@ fn signing_key_fp() -> ~str { } fn supported() -> bool { - let r = gpg(~[~"--version"]); + let r = gpgv(~[~"--version"]); r.status == 0 } @@ -88,15 +88,14 @@ fn add(root: &Path, key: &Path) { } } -fn verify(root: &Path, data: &Path, sig: &Path, keyfp: ~str) -> bool { +fn verify(root: &Path, data: &Path, sig: &Path) -> bool { let path = root.push("gpg"); - let p = gpg(~[~"--homedir", path.to_str(), - ~"--with-fingerprint", - ~"--verify", sig.to_str(), - data.to_str()]); - let res = ~"Primary key fingerprint: " + keyfp; - for str::split_char_each(p.err, '\n') |line| { - if line == res { return true; } + let res = gpgv(~[~"--homedir", path.to_str(), + ~"--keyring", ~"pubring.gpg", + ~"--verbose", + sig.to_str(), data.to_str()]); + if res.status != 0 { + return false; } - return false; + return true; } From ab89b5c294ac511d4d58809f9f20dfe4f2c8fe52 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sat, 13 Oct 2012 09:11:33 -0700 Subject: [PATCH 199/292] libstd: make Serializer a trait-level typaram --- src/libstd/json.rs | 28 ++ src/libstd/serialization.rs | 487 ++++++++++++++++++++++++++++ src/libsyntax/ast.rs | 49 +++ src/libsyntax/ext/auto_serialize.rs | 143 ++++---- src/test/run-pass/auto_serialize.rs | 62 ++-- 5 files changed, 692 insertions(+), 77 deletions(-) diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 0d3391c1867c..d170255b565d 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -273,6 +273,7 @@ pub impl PrettySerializer: serialization::Serializer { } } +#[cfg(stage0)] pub impl Json: serialization::Serializable { fn serialize(&self, s: &S) { match *self { @@ -296,6 +297,33 @@ pub impl Json: serialization::Serializable { } } +#[cfg(stage1)] +#[cfg(stage2)] +pub impl< + S: serialization::Serializer +> Json: serialization::Serializable { + fn serialize(&self, s: &S) { + match *self { + Number(v) => v.serialize(s), + String(ref v) => v.serialize(s), + Boolean(v) => v.serialize(s), + List(v) => v.serialize(s), + Object(ref v) => { + do s.emit_rec || { + let mut idx = 0; + for v.each |key, value| { + do s.emit_field(*key, idx) { + value.serialize(s); + } + idx += 1; + } + } + }, + Null => s.emit_nil(), + } + } +} + /// Serializes a json value into a io::writer pub fn to_writer(wr: io::Writer, json: &Json) { json.serialize(&Serializer(wr)) diff --git a/src/libstd/serialization.rs b/src/libstd/serialization.rs index b7cf09cc6aa5..9df2a326a847 100644 --- a/src/libstd/serialization.rs +++ b/src/libstd/serialization.rs @@ -92,6 +92,8 @@ pub trait Deserializer { fn read_tup_elt(&self, idx: uint, f: fn() -> T) -> T; } +#[cfg(stage0)] +pub mod traits { pub trait Serializable { fn serialize(&self, s: &S); } @@ -561,3 +563,488 @@ pub impl D: DeserializerHelpers { } } } +} + +#[cfg(stage1)] +#[cfg(stage2)] +pub mod traits { +pub trait Serializable { + fn serialize(&self, s: &S); +} + +pub trait Deserializable { + static fn deserialize(&self, d: &D) -> self; +} + +pub impl uint: Serializable { + fn serialize(&self, s: &S) { s.emit_uint(*self) } +} + +pub impl uint: Deserializable { + static fn deserialize(&self, d: &D) -> uint { + d.read_uint() + } +} + +pub impl u8: Serializable { + fn serialize(&self, s: &S) { s.emit_u8(*self) } +} + +pub impl u8: Deserializable { + static fn deserialize(&self, d: &D) -> u8 { + d.read_u8() + } +} + +pub impl u16: Serializable { + fn serialize(&self, s: &S) { s.emit_u16(*self) } +} + +pub impl u16: Deserializable { + static fn deserialize(&self, d: &D) -> u16 { + d.read_u16() + } +} + +pub impl u32: Serializable { + fn serialize(&self, s: &S) { s.emit_u32(*self) } +} + +pub impl u32: Deserializable { + static fn deserialize(&self, d: &D) -> u32 { + d.read_u32() + } +} + +pub impl u64: Serializable { + fn serialize(&self, s: &S) { s.emit_u64(*self) } +} + +pub impl u64: Deserializable { + static fn deserialize(&self, d: &D) -> u64 { + d.read_u64() + } +} + +pub impl int: Serializable { + fn serialize(&self, s: &S) { s.emit_int(*self) } +} + +pub impl int: Deserializable { + static fn deserialize(&self, d: &D) -> int { + d.read_int() + } +} + +pub impl i8: Serializable { + fn serialize(&self, s: &S) { s.emit_i8(*self) } +} + +pub impl i8: Deserializable { + static fn deserialize(&self, d: &D) -> i8 { + d.read_i8() + } +} + +pub impl i16: Serializable { + fn serialize(&self, s: &S) { s.emit_i16(*self) } +} + +pub impl i16: Deserializable { + static fn deserialize(&self, d: &D) -> i16 { + d.read_i16() + } +} + +pub impl i32: Serializable { + fn serialize(&self, s: &S) { s.emit_i32(*self) } +} + +pub impl i32: Deserializable { + static fn deserialize(&self, d: &D) -> i32 { + d.read_i32() + } +} + +pub impl i64: Serializable { + fn serialize(&self, s: &S) { s.emit_i64(*self) } +} + +pub impl i64: Deserializable { + static fn deserialize(&self, d: &D) -> i64 { + d.read_i64() + } +} + +pub impl &str: Serializable { + fn serialize(&self, s: &S) { s.emit_borrowed_str(*self) } +} + +pub impl ~str: Serializable { + fn serialize(&self, s: &S) { s.emit_owned_str(*self) } +} + +pub impl ~str: Deserializable { + static fn deserialize(&self, d: &D) -> ~str { + d.read_owned_str() + } +} + +pub impl @str: Serializable { + fn serialize(&self, s: &S) { s.emit_managed_str(*self) } +} + +pub impl @str: Deserializable { + static fn deserialize(&self, d: &D) -> @str { + d.read_managed_str() + } +} + +pub impl float: Serializable { + fn serialize(&self, s: &S) { s.emit_float(*self) } +} + +pub impl float: Deserializable { + static fn deserialize(&self, d: &D) -> float { + d.read_float() + } +} + +pub impl f32: Serializable { + fn serialize(&self, s: &S) { s.emit_f32(*self) } +} + +pub impl f32: Deserializable { + static fn deserialize(&self, d: &D) -> f32 { + d.read_f32() } +} + +pub impl f64: Serializable { + fn serialize(&self, s: &S) { s.emit_f64(*self) } +} + +pub impl f64: Deserializable { + static fn deserialize(&self, d: &D) -> f64 { + d.read_f64() + } +} + +pub impl bool: Serializable { + fn serialize(&self, s: &S) { s.emit_bool(*self) } +} + +pub impl bool: Deserializable { + static fn deserialize(&self, d: &D) -> bool { + d.read_bool() + } +} + +pub impl (): Serializable { + fn serialize(&self, s: &S) { s.emit_nil() } +} + +pub impl (): Deserializable { + static fn deserialize(&self, d: &D) -> () { + d.read_nil() + } +} + +pub impl> &T: Serializable { + fn serialize(&self, s: &S) { + s.emit_borrowed(|| (**self).serialize(s)) + } +} + +pub impl> ~T: Serializable { + fn serialize(&self, s: &S) { + s.emit_owned(|| (**self).serialize(s)) + } +} + +pub impl> ~T: Deserializable { + static fn deserialize(&self, d: &D) -> ~T { + d.read_owned(|| ~deserialize(d)) + } +} + +pub impl> @T: Serializable { + fn serialize(&self, s: &S) { + s.emit_managed(|| (**self).serialize(s)) + } +} + +pub impl> @T: Deserializable { + static fn deserialize(&self, d: &D) -> @T { + d.read_managed(|| @deserialize(d)) + } +} + +pub impl> &[T]: Serializable { + fn serialize(&self, s: &S) { + do s.emit_borrowed_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl> ~[T]: Serializable { + fn serialize(&self, s: &S) { + do s.emit_owned_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl> ~[T]: Deserializable { + static fn deserialize(&self, d: &D) -> ~[T] { + do d.read_owned_vec |len| { + do vec::from_fn(len) |i| { + d.read_vec_elt(i, || deserialize(d)) + } + } + } +} + +pub impl> @[T]: Serializable { + fn serialize(&self, s: &S) { + do s.emit_managed_vec(self.len()) { + for self.eachi |i, e| { + s.emit_vec_elt(i, || e.serialize(s)) + } + } + } +} + +pub impl> @[T]: Deserializable { + static fn deserialize(&self, d: &D) -> @[T] { + do d.read_managed_vec |len| { + do at_vec::from_fn(len) |i| { + d.read_vec_elt(i, || deserialize(d)) + } + } + } +} + +pub impl> Option: Serializable { + fn serialize(&self, s: &S) { + do s.emit_enum(~"option") { + match *self { + None => do s.emit_enum_variant(~"none", 0u, 0u) { + }, + + Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { + s.emit_enum_variant_arg(0u, || v.serialize(s)) + } + } + } + } +} + +pub impl> Option: Deserializable { + static fn deserialize(&self, d: &D) -> Option { + do d.read_enum(~"option") { + do d.read_enum_variant |i| { + match i { + 0 => None, + 1 => Some(d.read_enum_variant_arg(0u, || deserialize(d))), + _ => fail(#fmt("Bad variant for option: %u", i)) + } + } + } + } +} + +pub impl< + S: Serializer, + T0: Serializable, + T1: Serializable +> (T0, T1): Serializable { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1) => { + do s.emit_tup(2) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + } + } + } + } +} + +pub impl< + D: Deserializer, + T0: Deserializable, + T1: Deserializable +> (T0, T1): Deserializable { + static fn deserialize(&self, d: &D) -> (T0, T1) { + do d.read_tup(2) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)) + ) + } + } +} + +pub impl< + S: Serializer, + T0: Serializable, + T1: Serializable, + T2: Serializable +> (T0, T1, T2): Serializable { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2) => { + do s.emit_tup(3) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + } + } + } + } +} + +pub impl< + D: Deserializer, + T0: Deserializable, + T1: Deserializable, + T2: Deserializable +> (T0, T1, T2): Deserializable { + static fn deserialize(&self, d: &D) -> (T0, T1, T2) { + do d.read_tup(3) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)) + ) + } + } +} + +pub impl< + S: Serializer, + T0: Serializable, + T1: Serializable, + T2: Serializable, + T3: Serializable +> (T0, T1, T2, T3): Serializable { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2, ref t3) => { + do s.emit_tup(4) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + s.emit_tup_elt(3, || t3.serialize(s)); + } + } + } + } +} + +pub impl< + D: Deserializer, + T0: Deserializable, + T1: Deserializable, + T2: Deserializable, + T3: Deserializable +> (T0, T1, T2, T3): Deserializable { + static fn deserialize(&self, d: &D) -> (T0, T1, T2, T3) { + do d.read_tup(4) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)), + d.read_tup_elt(3, || deserialize(d)) + ) + } + } +} + +pub impl< + S: Serializer, + T0: Serializable, + T1: Serializable, + T2: Serializable, + T3: Serializable, + T4: Serializable +> (T0, T1, T2, T3, T4): Serializable { + fn serialize(&self, s: &S) { + match *self { + (ref t0, ref t1, ref t2, ref t3, ref t4) => { + do s.emit_tup(5) { + s.emit_tup_elt(0, || t0.serialize(s)); + s.emit_tup_elt(1, || t1.serialize(s)); + s.emit_tup_elt(2, || t2.serialize(s)); + s.emit_tup_elt(3, || t3.serialize(s)); + s.emit_tup_elt(4, || t4.serialize(s)); + } + } + } + } +} + +pub impl< + D: Deserializer, + T0: Deserializable, + T1: Deserializable, + T2: Deserializable, + T3: Deserializable, + T4: Deserializable +> (T0, T1, T2, T3, T4): Deserializable { + static fn deserialize(&self, d: &D) + -> (T0, T1, T2, T3, T4) { + do d.read_tup(5) { + ( + d.read_tup_elt(0, || deserialize(d)), + d.read_tup_elt(1, || deserialize(d)), + d.read_tup_elt(2, || deserialize(d)), + d.read_tup_elt(3, || deserialize(d)), + d.read_tup_elt(4, || deserialize(d)) + ) + } + } +} + +// ___________________________________________________________________________ +// Helper routines +// +// In some cases, these should eventually be coded as traits. + +pub trait SerializerHelpers { + fn emit_from_vec(&self, v: ~[T], f: fn(v: &T)); +} + +pub impl S: SerializerHelpers { + fn emit_from_vec(&self, v: ~[T], f: fn(v: &T)) { + do self.emit_owned_vec(v.len()) { + for v.eachi |i, e| { + do self.emit_vec_elt(i) { + f(e) + } + } + } + } +} + +pub trait DeserializerHelpers { + fn read_to_vec(&self, f: fn() -> T) -> ~[T]; +} + +pub impl D: DeserializerHelpers { + fn read_to_vec(&self, f: fn() -> T) -> ~[T] { + do self.read_owned_vec |len| { + do vec::from_fn(len) |i| { + self.read_vec_elt(i, || f()) + } + } + } +} +} + +pub use traits::*; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3740557b7f8f..cf7b758216b9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -7,17 +7,34 @@ use std::serialization::{Serializable, use codemap::{span, filename}; use parse::token; +#[cfg(stage0)] impl span: Serializable { /* Note #1972 -- spans are serialized but not deserialized */ fn serialize(&self, _s: &S) { } } +#[cfg(stage0)] impl span: Deserializable { static fn deserialize(_d: &D) -> span { ast_util::dummy_sp() } } +#[cfg(stage1)] +#[cfg(stage2)] +impl span: Serializable { + /* Note #1972 -- spans are serialized but not deserialized */ + fn serialize(&self, _s: &S) { } +} + +#[cfg(stage1)] +#[cfg(stage2)] +impl span: Deserializable { + static fn deserialize(_d: &D) -> span { + ast_util::dummy_sp() + } +} + #[auto_serialize] #[auto_deserialize] type spanned = {node: T, span: span}; @@ -34,6 +51,7 @@ macro_rules! interner_key ( // implemented. struct ident { repr: uint } +#[cfg(stage0)] impl ident: Serializable { fn serialize(&self, s: &S) { let intr = match unsafe { @@ -47,6 +65,7 @@ impl ident: Serializable { } } +#[cfg(stage0)] impl ident: Deserializable { static fn deserialize(d: &D) -> ident { let intr = match unsafe { @@ -60,6 +79,36 @@ impl ident: Deserializable { } } +#[cfg(stage1)] +#[cfg(stage2)] +impl ident: Serializable { + fn serialize(&self, s: &S) { + let intr = match unsafe { + task::local_data::local_data_get(interner_key!()) + } { + None => fail ~"serialization: TLS interner not set up", + Some(intr) => intr + }; + + s.emit_owned_str(*(*intr).get(*self)); + } +} + +#[cfg(stage1)] +#[cfg(stage2)] +impl ident: Deserializable { + static fn deserialize(d: &D) -> ident { + let intr = match unsafe { + task::local_data::local_data_get(interner_key!()) + } { + None => fail ~"deserialization: TLS interner not set up", + Some(intr) => intr + }; + + (*intr).intern(@d.read_owned_str()) + } +} + impl ident: cmp::Eq { pure fn eq(other: &ident) -> bool { self.repr == other.repr } pure fn ne(other: &ident) -> bool { !self.eq(other) } diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index b06536f4e026..452becbe559a 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -13,16 +13,16 @@ For example, a type like: would generate two implementations like: - impl Node: Serializable { - fn serialize(s: &S) { + impl node_id: Serializable { + fn serialize(s: &S) { do s.emit_struct("Node") { s.emit_field("id", 0, || s.emit_uint(self)) } } } - impl node_id: Deserializable { - static fn deserialize(d: &D) -> Node { + impl node_id: Deserializable { + static fn deserialize(d: &D) -> Node { do d.read_struct("Node") { Node { id: d.read_field(~"x", 0, || deserialize(d)) @@ -40,7 +40,10 @@ references other non-built-in types. A type definition like: would yield functions like: - impl spanned: Serializable { + impl< + S: Serializer, + T: Serializable + > spanned: Serializable { fn serialize(s: &S) { do s.emit_rec { s.emit_field("node", 0, || self.node.serialize(s)); @@ -49,8 +52,11 @@ would yield functions like: } } - impl spanned: Deserializable { - static fn deserialize(d: &D) -> spanned { + impl< + D: Deserializer, + T: Deserializable + > spanned: Deserializable { + static fn deserialize(d: &D) -> spanned { do d.read_rec { { node: d.read_field(~"node", 0, || deserialize(d)), @@ -215,6 +221,25 @@ fn expand_auto_deserialize( } priv impl ext_ctxt { + fn bind_path( + span: span, + ident: ast::ident, + path: @ast::path, + bounds: @~[ast::ty_param_bound] + ) -> ast::ty_param { + let bound = ast::bound_trait(@{ + id: self.next_id(), + node: ast::ty_path(path, self.next_id()), + span: span, + }); + + { + ident: ident, + id: self.next_id(), + bounds: @vec::append(~[bound], *bounds) + } + } + fn expr(span: span, node: ast::expr_) -> @ast::expr { @{id: self.next_id(), callee_id: self.next_id(), node: node, span: span} @@ -332,24 +357,28 @@ fn mk_impl( cx: ext_ctxt, span: span, ident: ast::ident, + ty_param: ast::ty_param, path: @ast::path, tps: ~[ast::ty_param], f: fn(@ast::ty) -> @ast::method ) -> @ast::item { // All the type parameters need to bound to the trait. - let trait_tps = do tps.map |tp| { - let t_bound = ast::bound_trait(@{ - id: cx.next_id(), - node: ast::ty_path(path, cx.next_id()), - span: span, - }); + let mut trait_tps = vec::append( + ~[ty_param], + do tps.map |tp| { + let t_bound = ast::bound_trait(@{ + id: cx.next_id(), + node: ast::ty_path(path, cx.next_id()), + span: span, + }); - { - ident: tp.ident, - id: cx.next_id(), - bounds: @vec::append(~[t_bound], *tp.bounds) + { + ident: tp.ident, + id: cx.next_id(), + bounds: @vec::append(~[t_bound], *tp.bounds) + } } - }; + ); let opt_trait = Some(@{ path: path, @@ -382,20 +411,37 @@ fn mk_ser_impl( tps: ~[ast::ty_param], body: @ast::expr ) -> @ast::item { + // Make a path to the std::serialization::Serializable typaram. + let ty_param = cx.bind_path( + span, + cx.ident_of(~"__S"), + cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Serializer"), + ] + ), + @~[] + ); + // Make a path to the std::serialization::Serializable trait. - let path = cx.path( + let path = cx.path_tps( span, ~[ cx.ident_of(~"std"), cx.ident_of(~"serialization"), cx.ident_of(~"Serializable"), - ] + ], + ~[cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[])] ); mk_impl( cx, span, ident, + ty_param, path, tps, |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) @@ -409,20 +455,37 @@ fn mk_deser_impl( tps: ~[ast::ty_param], body: @ast::expr ) -> @ast::item { + // Make a path to the std::serialization::Deserializable typaram. + let ty_param = cx.bind_path( + span, + cx.ident_of(~"__D"), + cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Deserializer"), + ] + ), + @~[] + ); + // Make a path to the std::serialization::Deserializable trait. - let path = cx.path( + let path = cx.path_tps( span, ~[ cx.ident_of(~"std"), cx.ident_of(~"serialization"), cx.ident_of(~"Deserializable"), - ] + ], + ~[cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[])] ); mk_impl( cx, span, ident, + ty_param, path, tps, |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) @@ -434,22 +497,6 @@ fn mk_ser_method( span: span, ser_body: ast::blk ) -> @ast::method { - let ser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization"), - cx.ident_of(~"Serializer"), - ], - ~[] - ); - - let ser_tps = ~[{ - ident: cx.ident_of(~"__S"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(ser_bound)], - }]; - let ty_s = @{ id: cx.next_id(), node: ast::ty_rptr( @@ -487,7 +534,7 @@ fn mk_ser_method( @{ ident: cx.ident_of(~"serialize"), attrs: ~[], - tps: ser_tps, + tps: ~[], self_ty: { node: ast::sty_region(ast::m_imm), span: span }, purity: ast::impure_fn, decl: ser_decl, @@ -505,22 +552,6 @@ fn mk_deser_method( ty: @ast::ty, deser_body: ast::blk ) -> @ast::method { - let deser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization"), - cx.ident_of(~"Deserializer"), - ], - ~[] - ); - - let deser_tps = ~[{ - ident: cx.ident_of(~"__D"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(deser_bound)], - }]; - let ty_d = @{ id: cx.next_id(), node: ast::ty_rptr( @@ -552,7 +583,7 @@ fn mk_deser_method( @{ ident: cx.ident_of(~"deserialize"), attrs: ~[], - tps: deser_tps, + tps: ~[], self_ty: { node: ast::sty_static, span: span }, purity: ast::impure_fn, decl: deser_decl, diff --git a/src/test/run-pass/auto_serialize.rs b/src/test/run-pass/auto_serialize.rs index 6c85f59b74ed..b63d1dcab7ec 100644 --- a/src/test/run-pass/auto_serialize.rs +++ b/src/test/run-pass/auto_serialize.rs @@ -9,18 +9,22 @@ use io::Writer; use std::serialization::{Serializable, Deserializable, deserialize}; use std::prettyprint; -fn test_ser_and_deser( - a1: &A, - +expected: ~str +fn test_prettyprint>( + a: &A, + expected: &~str ) { - // check the pretty printer: let s = do io::with_str_writer |w| { - a1.serialize(&prettyprint::Serializer(w)) + a.serialize(&prettyprint::Serializer(w)) }; debug!("s == %?", s); - assert s == expected; + assert s == *expected; +} - // check the EBML serializer: +fn test_ebml + Deserializable +>(a1: &A) { let bytes = do io::with_bytes_writer |wr| { let ebml_w = &ebml::Serializer(wr); a1.serialize(ebml_w) @@ -140,24 +144,40 @@ enum Quark { enum CLike { A, B, C } fn main() { - test_ser_and_deser(&Plus(@Minus(@Val(3u), @Val(10u)), - @Plus(@Val(22u), @Val(5u))), - ~"Plus(@Minus(@Val(3u), @Val(10u)), \ - @Plus(@Val(22u), @Val(5u)))"); + let a = &Plus(@Minus(@Val(3u), @Val(10u)), @Plus(@Val(22u), @Val(5u))); + test_prettyprint(a, &~"Plus(@Minus(@Val(3u), @Val(10u)), \ + @Plus(@Val(22u), @Val(5u)))"); + test_ebml(a); - test_ser_and_deser(&{lo: 0u, hi: 5u, node: 22u}, - ~"{lo: 0u, hi: 5u, node: 22u}"); + let a = &{lo: 0u, hi: 5u, node: 22u}; + test_prettyprint(a, &~"{lo: 0u, hi: 5u, node: 22u}"); + test_ebml(a); - test_ser_and_deser(&AnEnum({v: ~[1u, 2u, 3u]}), - ~"AnEnum({v: ~[1u, 2u, 3u]})"); + let a = &AnEnum({v: ~[1u, 2u, 3u]}); + test_prettyprint(a, &~"AnEnum({v: ~[1u, 2u, 3u]})"); + test_ebml(a); - test_ser_and_deser(&Point {x: 3u, y: 5u}, ~"Point {x: 3u, y: 5u}"); + let a = &Point {x: 3u, y: 5u}; + test_prettyprint(a, &~"Point {x: 3u, y: 5u}"); + test_ebml(a); - test_ser_and_deser(&@[1u, 2u, 3u], ~"@[1u, 2u, 3u]"); + let a = &@[1u, 2u, 3u]; + test_prettyprint(a, &~"@[1u, 2u, 3u]"); + test_ebml(a); - test_ser_and_deser(&Top(22u), ~"Top(22u)"); - test_ser_and_deser(&Bottom(222u), ~"Bottom(222u)"); + let a = &Top(22u); + test_prettyprint(a, &~"Top(22u)"); + test_ebml(a); - test_ser_and_deser(&A, ~"A"); - test_ser_and_deser(&B, ~"B"); + let a = &Bottom(222u); + test_prettyprint(a, &~"Bottom(222u)"); + test_ebml(a); + + let a = &A; + test_prettyprint(a, &~"A"); + test_ebml(a); + + let a = &B; + test_prettyprint(a, &~"B"); + test_ebml(a); } From f6211ab187abf18f458f289fef3c48b14a0a0af8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 12:00:32 -0700 Subject: [PATCH 200/292] Add various test cases (xfailed) --- src/test/auxiliary/issue_3136_a.rc | 3 +++ src/test/auxiliary/issue_3136_a.rs | 15 +++++++++++++++ src/test/compile-fail/issue-2074.rs | 12 ++++++++++++ src/test/compile-fail/issue-3214.rs | 8 ++++++++ src/test/run-pass/issue-2284.rs | 11 +++++++++++ src/test/run-pass/issue-3447.rs | 25 +++++++++++++++++++++++++ src/test/run-pass/issue-3521.rs | 10 ++++++++++ src/test/run-pass/issue_3136_b.rs | 6 ++++++ 8 files changed, 90 insertions(+) create mode 100644 src/test/auxiliary/issue_3136_a.rc create mode 100644 src/test/auxiliary/issue_3136_a.rs create mode 100644 src/test/compile-fail/issue-2074.rs create mode 100644 src/test/compile-fail/issue-3214.rs create mode 100644 src/test/run-pass/issue-2284.rs create mode 100644 src/test/run-pass/issue-3447.rs create mode 100644 src/test/run-pass/issue-3521.rs create mode 100644 src/test/run-pass/issue_3136_b.rs diff --git a/src/test/auxiliary/issue_3136_a.rc b/src/test/auxiliary/issue_3136_a.rc new file mode 100644 index 000000000000..532c669bd1d2 --- /dev/null +++ b/src/test/auxiliary/issue_3136_a.rc @@ -0,0 +1,3 @@ +#[crate_type = "lib"]; + +pub mod issue_3136_a; diff --git a/src/test/auxiliary/issue_3136_a.rs b/src/test/auxiliary/issue_3136_a.rs new file mode 100644 index 000000000000..b3af68803232 --- /dev/null +++ b/src/test/auxiliary/issue_3136_a.rs @@ -0,0 +1,15 @@ +trait x { + fn use_x(); +} +enum y = (); +impl y:x { + fn use_x() { + struct foo { //~ ERROR quux + i: () + } + fn new_foo(i: ()) -> foo { + foo { i: i } + } + } +} + diff --git a/src/test/compile-fail/issue-2074.rs b/src/test/compile-fail/issue-2074.rs new file mode 100644 index 000000000000..d911b7db3dd4 --- /dev/null +++ b/src/test/compile-fail/issue-2074.rs @@ -0,0 +1,12 @@ +// xfail-test +fn main() { + let one = fn@() -> uint { + enum r { a }; + return a as uint; + }; + let two = fn@() -> uint { + enum r { a }; + return a as uint; + }; + one(); two(); +} diff --git a/src/test/compile-fail/issue-3214.rs b/src/test/compile-fail/issue-3214.rs new file mode 100644 index 000000000000..3c783b99232d --- /dev/null +++ b/src/test/compile-fail/issue-3214.rs @@ -0,0 +1,8 @@ +// xfail-test +fn foo() { + struct foo { + mut x: T, //~ ERROR quux + drop { } + } +} +fn main() { } diff --git a/src/test/run-pass/issue-2284.rs b/src/test/run-pass/issue-2284.rs new file mode 100644 index 000000000000..3689c42253b9 --- /dev/null +++ b/src/test/run-pass/issue-2284.rs @@ -0,0 +1,11 @@ +// xfail-test +trait Send { + fn f(); +} + +fn f(t: T) { + t.f(); +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/run-pass/issue-3447.rs b/src/test/run-pass/issue-3447.rs new file mode 100644 index 000000000000..fab92ea6dcad --- /dev/null +++ b/src/test/run-pass/issue-3447.rs @@ -0,0 +1,25 @@ +// xfail-test +struct list { + element: &self/T, + mut next: Option<@list> +} + +impl list{ + fn addEnd(&self, element: &self/T) { + let newList = list { + element: element, + next: option::None + }; + + self.next = Some(@newList); + } +} + +fn main() { + let s = @"str"; + let ls: list<@str> = list { + element: &s, + next: option::None + }; + io::println(*ls.element); +} diff --git a/src/test/run-pass/issue-3521.rs b/src/test/run-pass/issue-3521.rs new file mode 100644 index 000000000000..d8693fe18d35 --- /dev/null +++ b/src/test/run-pass/issue-3521.rs @@ -0,0 +1,10 @@ +// xfail-test +fn main() { + let foo = 100; + + enum Stuff { + Bar = foo + } + + log(error, Bar); +} diff --git a/src/test/run-pass/issue_3136_b.rs b/src/test/run-pass/issue_3136_b.rs new file mode 100644 index 000000000000..ef8e1af56d70 --- /dev/null +++ b/src/test/run-pass/issue_3136_b.rs @@ -0,0 +1,6 @@ +// xfail-fast - check-fast doesn't understand aux-build +// aux-build:issue_3136_a.rc + +extern mod issue_3136_a; +fn main() {} + From 7237268b7040edf09dbbd9522b5656227a4b9b91 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 12:27:09 -0700 Subject: [PATCH 201/292] Allow enum discriminator exprs to refer to declared consts Also some work towards #3521 Closes #2428 --- src/libsyntax/visit.rs | 2 + src/rustc/middle/const_eval.rs | 220 +++++++++++++++----------- src/rustc/middle/resolve.rs | 58 ++++++- src/rustc/middle/typeck/check.rs | 33 ++-- src/test/compile-fail/issue-3521-2.rs | 7 + src/test/run-pass/issue-2428.rs | 10 ++ 6 files changed, 215 insertions(+), 115 deletions(-) create mode 100644 src/test/compile-fail/issue-3521-2.rs create mode 100644 src/test/run-pass/issue-2428.rs diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 50fbd21f7b8d..b402f9727dc2 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -182,6 +182,8 @@ fn visit_enum_def(enum_definition: ast::enum_def, tps: ~[ast::ty_param], visit_enum_def(enum_definition, tps, e, v); } } + // Visit the disr expr if it exists + vr.node.disr_expr.iter(|ex| v.visit_expr(*ex, e, v)); } } diff --git a/src/rustc/middle/const_eval.rs b/src/rustc/middle/const_eval.rs index 51382b8108cf..ea7b08140f39 100644 --- a/src/rustc/middle/const_eval.rs +++ b/src/rustc/middle/const_eval.rs @@ -1,4 +1,4 @@ -use syntax::{ast,ast_util,visit}; +use syntax::{ast,ast_map,ast_util,visit}; use ast::*; // @@ -135,28 +135,7 @@ fn classify(e: @expr, // FIXME: (#3728) we can probably do something CCI-ish // surrounding nonlocal constants. But we don't yet. ast::expr_path(_) => { - match def_map.find(e.id) { - Some(ast::def_const(def_id)) => { - if ast_util::is_local(def_id) { - let ty = ty::expr_ty(tcx, e); - if ty::type_is_integral(ty) { - integral_const - } else { - general_const - } - } else { - non_const - } - } - Some(_) => { - non_const - } - None => { - tcx.sess.span_bug(e.span, - ~"unknown path when \ - classifying constants"); - } - } + lookup_constness(tcx, e) } _ => non_const @@ -167,6 +146,40 @@ fn classify(e: @expr, } } +fn lookup_const(tcx: ty::ctxt, e: @expr) -> Option<@expr> { + match tcx.def_map.find(e.id) { + Some(ast::def_const(def_id)) => { + if ast_util::is_local(def_id) { + match tcx.items.find(def_id.node) { + None => None, + Some(ast_map::node_item(it, _)) => match it.node { + item_const(_, const_expr) => Some(const_expr), + _ => None + }, + Some(_) => None + } + } + else { None } + } + Some(_) => None, + None => None + } +} + +fn lookup_constness(tcx: ty::ctxt, e: @expr) -> constness { + match lookup_const(tcx, e) { + Some(rhs) => { + let ty = ty::expr_ty(tcx, rhs); + if ty::type_is_integral(ty) { + integral_const + } else { + general_const + } + } + None => non_const + } +} + fn process_crate(crate: @ast::crate, def_map: resolve::DefMap, tcx: ty::ctxt) { @@ -204,58 +217,67 @@ impl const_val : cmp::Eq { pure fn ne(other: &const_val) -> bool { !self.eq(other) } } -// FIXME: issue #1417 fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { + match eval_const_expr_partial(tcx, e) { + Ok(r) => r, + Err(s) => fail s + } +} + +fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) + -> Result { use middle::ty; - fn fromb(b: bool) -> const_val { const_int(b as i64) } + fn fromb(b: bool) -> Result { Ok(const_int(b as i64)) } match e.node { expr_unary(neg, inner) => { - match eval_const_expr(tcx, inner) { - const_float(f) => const_float(-f), - const_int(i) => const_int(-i), - const_uint(i) => const_uint(-i), - const_str(_) => fail ~"Negate on string", - const_bool(_) => fail ~"Negate on boolean" + match eval_const_expr_partial(tcx, inner) { + Ok(const_float(f)) => Ok(const_float(-f)), + Ok(const_int(i)) => Ok(const_int(-i)), + Ok(const_uint(i)) => Ok(const_uint(-i)), + Ok(const_str(_)) => Err(~"Negate on string"), + Ok(const_bool(_)) => Err(~"Negate on boolean"), + err => err } } expr_unary(not, inner) => { - match eval_const_expr(tcx, inner) { - const_int(i) => const_int(!i), - const_uint(i) => const_uint(!i), - const_bool(b) => const_bool(!b), - _ => fail ~"Not on float or string" + match eval_const_expr_partial(tcx, inner) { + Ok(const_int(i)) => Ok(const_int(!i)), + Ok(const_uint(i)) => Ok(const_uint(!i)), + Ok(const_bool(b)) => Ok(const_bool(!b)), + _ => Err(~"Not on float or string") } } expr_binary(op, a, b) => { - match (eval_const_expr(tcx, a), eval_const_expr(tcx, b)) { - (const_float(a), const_float(b)) => { + match (eval_const_expr_partial(tcx, a), + eval_const_expr_partial(tcx, b)) { + (Ok(const_float(a)), Ok(const_float(b))) => { match op { - add => const_float(a + b), - subtract => const_float(a - b), - mul => const_float(a * b), - div => const_float(a / b), - rem => const_float(a % b), + add => Ok(const_float(a + b)), + subtract => Ok(const_float(a - b)), + mul => Ok(const_float(a * b)), + div => Ok(const_float(a / b)), + rem => Ok(const_float(a % b)), eq => fromb(a == b), lt => fromb(a < b), le => fromb(a <= b), ne => fromb(a != b), ge => fromb(a >= b), gt => fromb(a > b), - _ => fail ~"Can't do this op on floats" + _ => Err(~"Can't do this op on floats") } } - (const_int(a), const_int(b)) => { + (Ok(const_int(a)), Ok(const_int(b))) => { match op { - add => const_int(a + b), - subtract => const_int(a - b), - mul => const_int(a * b), - div => const_int(a / b), - rem => const_int(a % b), - and | bitand => const_int(a & b), - or | bitor => const_int(a | b), - bitxor => const_int(a ^ b), - shl => const_int(a << b), - shr => const_int(a >> b), + add => Ok(const_int(a + b)), + subtract => Ok(const_int(a - b)), + mul => Ok(const_int(a * b)), + div => Ok(const_int(a / b)), + rem => Ok(const_int(a % b)), + and | bitand => Ok(const_int(a & b)), + or | bitor => Ok(const_int(a | b)), + bitxor => Ok(const_int(a ^ b)), + shl => Ok(const_int(a << b)), + shr => Ok(const_int(a >> b)), eq => fromb(a == b), lt => fromb(a < b), le => fromb(a <= b), @@ -264,18 +286,18 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { gt => fromb(a > b) } } - (const_uint(a), const_uint(b)) => { + (Ok(const_uint(a)), Ok(const_uint(b))) => { match op { - add => const_uint(a + b), - subtract => const_uint(a - b), - mul => const_uint(a * b), - div => const_uint(a / b), - rem => const_uint(a % b), - and | bitand => const_uint(a & b), - or | bitor => const_uint(a | b), - bitxor => const_uint(a ^ b), - shl => const_uint(a << b), - shr => const_uint(a >> b), + add => Ok(const_uint(a + b)), + subtract => Ok(const_uint(a - b)), + mul => Ok(const_uint(a * b)), + div => Ok(const_uint(a / b)), + rem => Ok(const_uint(a % b)), + and | bitand => Ok(const_uint(a & b)), + or | bitor => Ok(const_uint(a | b)), + bitxor => Ok(const_uint(a ^ b)), + shl => Ok(const_uint(a << b)), + shr => Ok(const_uint(a >> b)), eq => fromb(a == b), lt => fromb(a < b), le => fromb(a <= b), @@ -285,22 +307,22 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { } } // shifts can have any integral type as their rhs - (const_int(a), const_uint(b)) => { + (Ok(const_int(a)), Ok(const_uint(b))) => { match op { - shl => const_int(a << b), - shr => const_int(a >> b), - _ => fail ~"Can't do this op on an int and uint" + shl => Ok(const_int(a << b)), + shr => Ok(const_int(a >> b)), + _ => Err(~"Can't do this op on an int and uint") } } - (const_uint(a), const_int(b)) => { + (Ok(const_uint(a)), Ok(const_int(b))) => { match op { - shl => const_uint(a << b), - shr => const_uint(a >> b), - _ => fail ~"Can't do this op on a uint and int" + shl => Ok(const_uint(a << b)), + shr => Ok(const_uint(a >> b)), + _ => Err(~"Can't do this op on a uint and int") } } - (const_bool(a), const_bool(b)) => { - const_bool(match op { + (Ok(const_bool(a)), Ok(const_bool(b))) => { + Ok(const_bool(match op { and => a && b, or => a || b, bitxor => a ^ b, @@ -308,47 +330,53 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { bitor => a | b, eq => a == b, ne => a != b, - _ => fail ~"Can't do this op on bools" - }) + _ => return Err(~"Can't do this op on bools") + })) } - _ => fail ~"Bad operands for binary" + _ => Err(~"Bad operands for binary") } } expr_cast(base, _) => { let ety = ty::expr_ty(tcx, e); - let base = eval_const_expr(tcx, base); + let base = eval_const_expr_partial(tcx, base); match ty::get(ety).sty { ty::ty_float(_) => { match base { - const_uint(u) => const_float(u as f64), - const_int(i) => const_float(i as f64), - const_float(_) => base, - _ => fail ~"Can't cast float to str" + Ok(const_uint(u)) => Ok(const_float(u as f64)), + Ok(const_int(i)) => Ok(const_float(i as f64)), + Ok(const_float(_)) => base, + _ => Err(~"Can't cast float to str") } } ty::ty_uint(_) => { match base { - const_uint(_) => base, - const_int(i) => const_uint(i as u64), - const_float(f) => const_uint(f as u64), - _ => fail ~"Can't cast str to uint" + Ok(const_uint(_)) => base, + Ok(const_int(i)) => Ok(const_uint(i as u64)), + Ok(const_float(f)) => Ok(const_uint(f as u64)), + _ => Err(~"Can't cast str to uint") } } ty::ty_int(_) | ty::ty_bool => { match base { - const_uint(u) => const_int(u as i64), - const_int(_) => base, - const_float(f) => const_int(f as i64), - _ => fail ~"Can't cast str to int" + Ok(const_uint(u)) => Ok(const_int(u as i64)), + Ok(const_int(_)) => base, + Ok(const_float(f)) => Ok(const_int(f as i64)), + _ => Err(~"Can't cast str to int") } } - _ => fail ~"Can't cast this type" + _ => Err(~"Can't cast this type") } } - expr_lit(lit) => lit_to_const(lit), + expr_path(_) => { + match lookup_const(tcx, e) { + Some(actual_e) => eval_const_expr_partial(tcx, actual_e), + None => Err(~"Non-constant path in constant expr") + } + } + expr_lit(lit) => Ok(lit_to_const(lit)), // If we have a vstore, just keep going; it has to be a string - expr_vstore(e, _) => eval_const_expr(tcx, e), - _ => fail ~"Unsupported constant expr" + expr_vstore(e, _) => eval_const_expr_partial(tcx, e), + _ => Err(~"Unsupported constant expr") } } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 045905bbe07b..b6e1729a07a7 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -257,7 +257,10 @@ enum RibKind { MethodRibKind(node_id, MethodSort), // We passed through a function *item* scope. Disallow upvars. - OpaqueFunctionRibKind + OpaqueFunctionRibKind, + + // We're in a constant item. Can't refer to dynamic stuff. + ConstantItemRibKind } // Methods can be required or provided. Required methods only occur in traits. @@ -3114,9 +3117,16 @@ impl Resolver { return None; } + ConstantItemRibKind => { + // Still doesn't deal with upvars + self.session.span_err(span, + ~"attempt to use a non-constant \ + value in a constant"); + + } } - rib_index += 1u; + rib_index += 1; } return Some(dl_def(def)); @@ -3130,8 +3140,8 @@ impl Resolver { // XXX: Try caching? let mut i = (*ribs).len(); - while i != 0u { - i -= 1u; + while i != 0 { + i -= 1; let rib = (*ribs).get_elt(i); match rib.bindings.find(name) { Some(def_like) => { @@ -3179,7 +3189,33 @@ impl Resolver { } match item.node { - item_enum(_, type_parameters) | + + // enum item: resolve all the variants' discrs, + // then resolve the ty params + item_enum(enum_def, type_parameters) => { + + for enum_def.variants.each() |variant| { + do variant.node.disr_expr.iter() |dis_expr| { + // resolve the discriminator expr + // as a constant + self.with_constant_rib(|| { + self.resolve_expr(*dis_expr, visitor); + }); + } + } + + // n.b. the discr expr gets visted twice. + // but maybe it's okay since the first time will signal an + // error if there is one? -- tjc + do self.with_type_parameter_rib + (HasTypeParameters(&type_parameters, item.id, 0, + NormalRibKind)) + || { + + visit_item(item, (), visitor); + } + } + item_ty(_, type_parameters) => { do self.with_type_parameter_rib (HasTypeParameters(&type_parameters, item.id, 0u, @@ -3344,7 +3380,9 @@ impl Resolver { } item_const(*) => { - visit_item(item, (), visitor); + self.with_constant_rib(|| { + visit_item(item, (), visitor); + }); } item_mac(*) => { @@ -3401,6 +3439,12 @@ impl Resolver { f(); (*self.label_ribs).pop(); } + fn with_constant_rib(f: fn()) { + (*self.value_ribs).push(@Rib(ConstantItemRibKind)); + f(); + (*self.value_ribs).pop(); + } + fn resolve_function(rib_kind: RibKind, optional_declaration: Option<@fn_decl>, @@ -4127,7 +4171,7 @@ impl Resolver { namespace); } - if path.idents.len() > 1u { + if path.idents.len() > 1 { return self.resolve_module_relative_path(path, self.xray_context, namespace); diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 2bf124526ac8..9a7f2192cb14 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2219,9 +2219,14 @@ fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool { fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) { let rty = ty::node_id_to_type(ccx.tcx, id); let fcx = blank_fn_ctxt(ccx, rty, e.id); + let declty = fcx.ccx.tcx.tcache.get(local_def(id)).ty; + check_const_with_ty(fcx, _sp, e, declty); +} + +fn check_const_with_ty(fcx: @fn_ctxt, _sp: span, e: @ast::expr, + declty: ty::t) { check_expr(fcx, e, None); let cty = fcx.expr_ty(e); - let declty = fcx.ccx.tcx.tcache.get(local_def(id)).ty; demand::suptype(fcx, e.span, declty, cty); regionck::regionck_expr(fcx, e); writeback::resolve_type_vars_in_expr(fcx, e); @@ -2259,27 +2264,31 @@ fn check_enum_variants(ccx: @crate_ctxt, variants: &mut ~[ty::variant_info]) { let rty = ty::node_id_to_type(ccx.tcx, id); for vs.each |v| { - match v.node.disr_expr { - Some(e) => { - let fcx = blank_fn_ctxt(ccx, rty, e.id); - check_expr(fcx, e, None); - let cty = fcx.expr_ty(e); + do v.node.disr_expr.iter |e_ref| { + let e = *e_ref; + debug!("disr expr, checking %s", + expr_to_str(e, ccx.tcx.sess.intr())); let declty = ty::mk_int(ccx.tcx); - demand::suptype(fcx, e.span, declty, cty); + let fcx = blank_fn_ctxt(ccx, rty, e.id); + check_const_with_ty(fcx, e.span, e, declty); // check_expr (from check_const pass) doesn't guarantee // that the expression is in an form that eval_const_expr can // handle, so we may still get an internal compiler error - match const_eval::eval_const_expr(ccx.tcx, e) { - const_eval::const_int(val) => { + + match const_eval::eval_const_expr_partial(ccx.tcx, e) { + Ok(const_eval::const_int(val)) => { *disr_val = val as int; } - _ => { + Ok(_) => { ccx.tcx.sess.span_err(e.span, ~"expected signed integer \ constant"); } + Err(err) => { + ccx.tcx.sess.span_err(e.span, + #fmt("expected constant: %s", err)); + + } } - } - _ => () } if vec::contains(*disr_vals, &*disr_val) { ccx.tcx.sess.span_err(v.span, diff --git a/src/test/compile-fail/issue-3521-2.rs b/src/test/compile-fail/issue-3521-2.rs new file mode 100644 index 000000000000..5af0417af047 --- /dev/null +++ b/src/test/compile-fail/issue-3521-2.rs @@ -0,0 +1,7 @@ +fn main() { + let foo = 100; + + const y: int = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant + + log(error, y); +} diff --git a/src/test/run-pass/issue-2428.rs b/src/test/run-pass/issue-2428.rs new file mode 100644 index 000000000000..76fc674e7344 --- /dev/null +++ b/src/test/run-pass/issue-2428.rs @@ -0,0 +1,10 @@ +fn main() { + let foo = 100; + const quux: int = 5; + + enum Stuff { + Bar = quux + } + + assert (Bar as int == quux); +} From 0643466f85a765bbd0d7ec14a96e0980795aebec Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 13:14:23 -0700 Subject: [PATCH 202/292] Fix whitespace --- src/rustc/middle/resolve.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index b6e1729a07a7..ba8e6c26274a 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -3199,7 +3199,7 @@ impl Resolver { // resolve the discriminator expr // as a constant self.with_constant_rib(|| { - self.resolve_expr(*dis_expr, visitor); + self.resolve_expr(*dis_expr, visitor); }); } } @@ -3215,7 +3215,7 @@ impl Resolver { visit_item(item, (), visitor); } } - + item_ty(_, type_parameters) => { do self.with_type_parameter_rib (HasTypeParameters(&type_parameters, item.id, 0u, From 2a1aa9fb5356dc43e649b86622bd12463722d2af Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 14 Oct 2012 13:39:17 -0700 Subject: [PATCH 203/292] Check whether loans conflict with old loans or with themselves. Along the way, convert from dvec-of-dvec representation to track loans in scope to just a single flattened list. It's more convenient. Fixes #3765. r+ pcwalton. --- src/rustc/middle/borrowck.rs | 9 +- src/rustc/middle/borrowck/check_loans.rs | 83 +++++++++------- src/rustc/middle/borrowck/gather_loans.rs | 95 +++++++++++-------- src/rustc/middle/borrowck/loan.rs | 45 +++++---- ...borrowck-loan-local-as-both-mut-and-imm.rs | 25 +++++ 5 files changed, 164 insertions(+), 93 deletions(-) create mode 100644 src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index e2f7ba20642a..02fd2998f4db 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -383,7 +383,7 @@ impl bckerr : cmp::Eq { type bckres = Result; /// a complete record of a loan that was granted -type loan = {lp: @loan_path, cmt: cmt, mutbl: ast::mutability}; +struct Loan {lp: @loan_path, cmt: cmt, mutbl: ast::mutability} /// maps computed by `gather_loans` that are then used by `check_loans` /// @@ -392,7 +392,7 @@ type loan = {lp: @loan_path, cmt: cmt, mutbl: ast::mutability}; /// - `pure_map`: map from block/expr that must be pure to the error message /// that should be reported if they are not pure type req_maps = { - req_loan_map: HashMap>>, + req_loan_map: HashMap>, pure_map: HashMap }; @@ -582,6 +582,11 @@ impl borrowck_ctxt { method_map: self.method_map}; mc.mut_to_str(mutbl) } + + fn loan_to_repr(loan: &Loan) -> ~str { + fmt!("Loan(lp=%?, cmt=%s, mutbl=%?)", + loan.lp, self.cmt_to_repr(loan.cmt), loan.mutbl) + } } // The inherent mutability of a component is its default mutability diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index 6a9195b45096..7f95d44fd3b8 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -131,18 +131,15 @@ impl check_loan_ctxt { } } - fn walk_loans(scope_id: ast::node_id, - f: fn(v: &loan) -> bool) { + fn walk_loans(scope_id: ast::node_id, f: fn(v: &Loan) -> bool) { let mut scope_id = scope_id; let region_map = self.tcx().region_map; let req_loan_map = self.req_maps.req_loan_map; loop { - for req_loan_map.find(scope_id).each |loanss| { - for loanss.each |loans| { - for loans.each |loan| { - if !f(loan) { return; } - } + for req_loan_map.find(scope_id).each |loans| { + for loans.each |loan| { + if !f(loan) { return; } } } @@ -155,7 +152,7 @@ impl check_loan_ctxt { fn walk_loans_of(scope_id: ast::node_id, lp: @loan_path, - f: fn(v: &loan) -> bool) { + f: fn(v: &Loan) -> bool) { for self.walk_loans(scope_id) |loan| { if loan.lp == lp { if !f(loan) { return; } @@ -256,36 +253,58 @@ impl check_loan_ctxt { } fn check_for_conflicting_loans(scope_id: ast::node_id) { - let new_loanss = match self.req_maps.req_loan_map.find(scope_id) { + debug!("check_for_conflicting_loans(scope_id=%?)", scope_id); + + let new_loans = match self.req_maps.req_loan_map.find(scope_id) { None => return, - Some(loanss) => loanss + Some(loans) => loans }; + debug!("new_loans has length %?", new_loans.len()); + let par_scope_id = self.tcx().region_map.get(scope_id); for self.walk_loans(par_scope_id) |old_loan| { - for new_loanss.each |new_loans| { - for new_loans.each |new_loan| { - if old_loan.lp != new_loan.lp { loop; } - match (old_loan.mutbl, new_loan.mutbl) { - (m_const, _) | (_, m_const) | - (m_mutbl, m_mutbl) | (m_imm, m_imm) => { - /*ok*/ - } + debug!("old_loan=%?", self.bccx.loan_to_repr(old_loan)); - (m_mutbl, m_imm) | (m_imm, m_mutbl) => { - self.bccx.span_err( - new_loan.cmt.span, - fmt!("loan of %s as %s \ - conflicts with prior loan", - self.bccx.cmt_to_str(new_loan.cmt), - self.bccx.mut_to_str(new_loan.mutbl))); - self.bccx.span_note( - old_loan.cmt.span, - fmt!("prior loan as %s granted here", - self.bccx.mut_to_str(old_loan.mutbl))); - } - } - } + for new_loans.each |new_loan| { + self.report_error_if_loans_conflict(old_loan, new_loan); + } + } + + let len = new_loans.len(); + for uint::range(0, len) |i| { + let loan_i = new_loans[i]; + for uint::range(i+1, len) |j| { + let loan_j = new_loans[j]; + self.report_error_if_loans_conflict(&loan_i, &loan_j); + } + } + } + + fn report_error_if_loans_conflict(&self, + old_loan: &Loan, + new_loan: &Loan) { + if old_loan.lp != new_loan.lp { + return; + } + + match (old_loan.mutbl, new_loan.mutbl) { + (m_const, _) | (_, m_const) | + (m_mutbl, m_mutbl) | (m_imm, m_imm) => { + /*ok*/ + } + + (m_mutbl, m_imm) | (m_imm, m_mutbl) => { + self.bccx.span_err( + new_loan.cmt.span, + fmt!("loan of %s as %s \ + conflicts with prior loan", + self.bccx.cmt_to_str(new_loan.cmt), + self.bccx.mut_to_str(new_loan.mutbl))); + self.bccx.span_note( + old_loan.cmt.span, + fmt!("prior loan as %s granted here", + self.bccx.mut_to_str(old_loan.mutbl))); } } } diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index a2c8f1850713..e8d11fd1708f 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -213,9 +213,10 @@ fn req_loans_in_expr(ex: @ast::expr, } impl gather_loan_ctxt { - fn tcx() -> ty::ctxt { self.bccx.tcx } + fn tcx(&self) -> ty::ctxt { self.bccx.tcx } - fn guarantee_adjustments(expr: @ast::expr, + fn guarantee_adjustments(&self, + expr: @ast::expr, adjustment: &ty::AutoAdjustment) { debug!("guarantee_adjustments(expr=%s, adjustment=%?)", expr_repr(self.tcx(), expr), adjustment); @@ -256,7 +257,8 @@ impl gather_loan_ctxt { // out loans, which will be added to the `req_loan_map`. This can // also entail "rooting" GC'd pointers, which means ensuring // dynamically that they are not freed. - fn guarantee_valid(cmt: cmt, + fn guarantee_valid(&self, + cmt: cmt, req_mutbl: ast::mutability, scope_r: ty::region) { @@ -280,35 +282,12 @@ impl gather_loan_ctxt { // it within that scope, the loan will be detected and an // error will be reported. Some(_) => { - match self.bccx.loan(cmt, scope_r, req_mutbl) { - Err(e) => { self.bccx.report(e); } - Ok(loans) if loans.len() == 0 => {} - Ok(loans) => { - match scope_r { - ty::re_scope(scope_id) => { - self.add_loans(scope_id, loans); - - if req_mutbl == m_imm && cmt.mutbl != m_imm { - self.bccx.loaned_paths_imm += 1; - - if self.tcx().sess.borrowck_note_loan() { - self.bccx.span_note( - cmt.span, - fmt!("immutable loan required")); - } - } else { - self.bccx.loaned_paths_same += 1; - } + match self.bccx.loan(cmt, scope_r, req_mutbl) { + Err(e) => { self.bccx.report(e); } + Ok(move loans) => { + self.add_loans(cmt, req_mutbl, scope_r, move loans); } - _ => { - self.bccx.tcx.sess.span_bug( - cmt.span, - fmt!("loans required but scope is scope_region is %s", - region_to_str(self.tcx(), scope_r))); - } - } } - } } // The path is not loanable: in that case, we must try and @@ -385,7 +364,8 @@ impl gather_loan_ctxt { // has type `@mut{f:int}`, this check might fail because `&x.f` // reqires an immutable pointer, but `f` lives in (aliased) // mutable memory. - fn check_mutbl(req_mutbl: ast::mutability, + fn check_mutbl(&self, + req_mutbl: ast::mutability, cmt: cmt) -> bckres { debug!("check_mutbl(req_mutbl=%?, cmt.mutbl=%?)", req_mutbl, cmt.mutbl); @@ -407,21 +387,58 @@ impl gather_loan_ctxt { } } - fn add_loans(scope_id: ast::node_id, loans: @DVec) { + fn add_loans(&self, + cmt: cmt, + req_mutbl: ast::mutability, + scope_r: ty::region, + +loans: ~[Loan]) { + if loans.len() == 0 { + return; + } + + let scope_id = match scope_r { + ty::re_scope(scope_id) => scope_id, + _ => { + self.bccx.tcx.sess.span_bug( + cmt.span, + fmt!("loans required but scope is scope_region is %s", + region_to_str(self.tcx(), scope_r))); + } + }; + + self.add_loans_to_scope_id(scope_id, move loans); + + if req_mutbl == m_imm && cmt.mutbl != m_imm { + self.bccx.loaned_paths_imm += 1; + + if self.tcx().sess.borrowck_note_loan() { + self.bccx.span_note( + cmt.span, + fmt!("immutable loan required")); + } + } else { + self.bccx.loaned_paths_same += 1; + } + } + + fn add_loans_to_scope_id(&self, scope_id: ast::node_id, +loans: ~[Loan]) { debug!("adding %u loans to scope_id %?", loans.len(), scope_id); match self.req_maps.req_loan_map.find(scope_id) { - Some(l) => { - l.push(loans); + Some(req_loans) => { + req_loans.push_all(loans); } None => { - self.req_maps.req_loan_map.insert( - scope_id, @dvec::from_vec(~[loans])); + let dvec = @dvec::from_vec(move loans); + self.req_maps.req_loan_map.insert(scope_id, dvec); } } } - fn gather_pat(discr_cmt: cmt, root_pat: @ast::pat, - arm_id: ast::node_id, alt_id: ast::node_id) { + fn gather_pat(&self, + discr_cmt: cmt, + root_pat: @ast::pat, + arm_id: ast::node_id, + alt_id: ast::node_id) { do self.bccx.cat_pattern(discr_cmt, root_pat) |cmt, pat| { match pat.node { ast::pat_ident(bm, _, _) if !self.pat_is_variant(pat) => { @@ -475,7 +492,7 @@ impl gather_loan_ctxt { } } - fn pat_is_variant(pat: @ast::pat) -> bool { + fn pat_is_variant(&self, pat: @ast::pat) -> bool { pat_util::pat_is_variant(self.bccx.tcx.def_map, pat) } } diff --git a/src/rustc/middle/borrowck/loan.rs b/src/rustc/middle/borrowck/loan.rs index 8d9d7a5796a9..5d3ccc392139 100644 --- a/src/rustc/middle/borrowck/loan.rs +++ b/src/rustc/middle/borrowck/loan.rs @@ -8,35 +8,37 @@ use result::{Result, Ok, Err}; impl borrowck_ctxt { fn loan(cmt: cmt, scope_region: ty::region, - mutbl: ast::mutability) -> bckres<@DVec> { - let lc = loan_ctxt_(@{bccx: self, - scope_region: scope_region, - loans: @DVec()}); + mutbl: ast::mutability) -> bckres<~[Loan]> { + let lc = LoanContext { + bccx: self, + scope_region: scope_region, + loans: ~[] + }; match lc.loan(cmt, mutbl) { - Ok(()) => {Ok(lc.loans)} - Err(e) => {Err(e)} + Err(e) => Err(e), + Ok(()) => { + let LoanContext {loans, _} = move lc; + Ok(loans) + } } } } -type loan_ctxt_ = { +struct LoanContext { bccx: borrowck_ctxt, // the region scope for which we must preserve the memory scope_region: ty::region, // accumulated list of loans that will be required - loans: @DVec -}; - -enum loan_ctxt { - loan_ctxt_(@loan_ctxt_) + mut loans: ~[Loan] } -impl loan_ctxt { - fn tcx() -> ty::ctxt { self.bccx.tcx } +impl LoanContext { + fn tcx(&self) -> ty::ctxt { self.bccx.tcx } - fn issue_loan(cmt: cmt, + fn issue_loan(&self, + cmt: cmt, scope_ub: ty::region, req_mutbl: ast::mutability) -> bckres<()> { if self.bccx.is_subregion_of(self.scope_region, scope_ub) { @@ -57,12 +59,13 @@ impl loan_ctxt { } } - (*self.loans).push({ + self.loans.push(Loan { // Note: cmt.lp must be Some(_) because otherwise this // loan process does not apply at all. lp: cmt.lp.get(), cmt: cmt, - mutbl: req_mutbl}); + mutbl: req_mutbl + }); return Ok(()); } else { // The loan being requested lives longer than the data @@ -73,7 +76,7 @@ impl loan_ctxt { } } - fn loan(cmt: cmt, req_mutbl: ast::mutability) -> bckres<()> { + fn loan(&self, cmt: cmt, req_mutbl: ast::mutability) -> bckres<()> { debug!("loan(%s, %s)", self.bccx.cmt_to_repr(cmt), self.bccx.mut_to_str(req_mutbl)); @@ -144,7 +147,8 @@ impl loan_ctxt { // A "stable component" is one where assigning the base of the // component cannot cause the component itself to change types. // Example: record fields. - fn loan_stable_comp(cmt: cmt, + fn loan_stable_comp(&self, + cmt: cmt, cmt_base: cmt, req_mutbl: ast::mutability) -> bckres<()> { let base_mutbl = match req_mutbl { @@ -162,7 +166,8 @@ impl loan_ctxt { // An "unstable deref" means a deref of a ptr/comp where, if the // base of the deref is assigned to, pointers into the result of the // deref would be invalidated. Examples: interior of variants, uniques. - fn loan_unstable_deref(cmt: cmt, + fn loan_unstable_deref(&self, + cmt: cmt, cmt_base: cmt, req_mutbl: ast::mutability) -> bckres<()> { // Variant components: the base must be immutable, because diff --git a/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs b/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs new file mode 100644 index 000000000000..54048ed2fd8c --- /dev/null +++ b/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs @@ -0,0 +1,25 @@ +use core::either::{Either, Left, Right}; + + fn f(x: &mut Either, y: &Either) -> int { + match *y { + Left(ref z) => { + *x = Right(1.0); + *z + } + _ => fail + } + } + + fn g() { + let mut x: Either = Left(3); + io::println(f(&mut x, &x).to_str()); //~ ERROR conflicts with prior loan + } + + fn h() { + let mut x: Either = Left(3); + let y: &Either = &x; + let z: &mut Either = &mut x; //~ ERROR conflicts with prior loan + *z = *y; + } + + fn main() {} From c886629d4f2fb4a2712884b07de38101e9dc956c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 8 Oct 2012 12:39:30 -0700 Subject: [PATCH 204/292] rustc: Implement monomorphic default methods. r=nmatsakis --- src/rustc/metadata/common.rs | 2 + src/rustc/metadata/csearch.rs | 14 + src/rustc/metadata/decoder.rs | 54 +++- src/rustc/metadata/encoder.rs | 30 ++- src/rustc/middle/resolve.rs | 21 +- src/rustc/middle/trans/base.rs | 94 ++----- src/rustc/middle/trans/callee.rs | 28 +- src/rustc/middle/trans/closure.rs | 4 +- src/rustc/middle/trans/common.rs | 30 ++- src/rustc/middle/trans/expr.rs | 4 +- src/rustc/middle/trans/foreign.rs | 4 +- src/rustc/middle/trans/inline.rs | 19 +- src/rustc/middle/trans/meth.rs | 91 +++++-- src/rustc/middle/trans/monomorphize.rs | 63 ++++- src/rustc/middle/trans/type_use.rs | 9 +- src/rustc/middle/ty.rs | 51 ++-- src/rustc/middle/typeck.rs | 9 +- src/rustc/middle/typeck/check/method.rs | 72 +++-- src/rustc/middle/typeck/check/vtable.rs | 2 +- src/rustc/middle/typeck/coherence.rs | 295 +++++++++++++-------- src/rustc/middle/typeck/collect.rs | 19 +- src/test/run-pass/default-method-simple.rs | 23 ++ 22 files changed, 638 insertions(+), 300 deletions(-) create mode 100644 src/test/run-pass/default-method-simple.rs diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs index 1857abf2cf2f..972d48a61353 100644 --- a/src/rustc/metadata/common.rs +++ b/src/rustc/metadata/common.rs @@ -124,5 +124,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f tag_table_legacy_boxed_trait = 0x63 } +const tag_item_trait_method_sort: uint = 0x70; + type link_meta = {name: ~str, vers: ~str, extras_hash: ~str}; diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index 5f5f938541f1..ea6bd499a3b5 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -23,6 +23,7 @@ export get_region_param; export get_enum_variants; export get_impls_for_mod; export get_trait_methods; +export get_provided_trait_methods; export get_method_names_if_trait; export get_item_attrs; export each_path; @@ -31,6 +32,12 @@ export get_impl_traits; export get_impl_method; export get_item_path; export maybe_get_item_ast, found_ast, found, found_parent, not_found; +export ProvidedTraitMethodInfo; + +struct ProvidedTraitMethodInfo { + ty: ty::method, + def_id: ast::def_id +} fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> ~str { let cdata = cstore::get_crate_data(cstore, def.crate).data; @@ -99,6 +106,13 @@ fn get_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> @~[ty::method] { decoder::get_trait_methods(cstore.intr, cdata, def.node, tcx) } +fn get_provided_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> + ~[ProvidedTraitMethodInfo] { + let cstore = tcx.cstore; + let cdata = cstore::get_crate_data(cstore, def.crate); + decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx) +} + fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id) -> Option<@DVec<(ast::ident, ast::self_ty_)>> { diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index e639449a8573..f0911bd1aa27 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -19,6 +19,7 @@ use syntax::diagnostic::span_handler; use common::*; use syntax::parse::token::ident_interner; use hash::{Hash, HashUtil}; +use csearch::ProvidedTraitMethodInfo; export class_dtor; export get_class_fields; @@ -40,6 +41,7 @@ export get_crate_hash; export get_crate_vers; export get_impls_for_mod; export get_trait_methods; +export get_provided_trait_methods; export get_method_names_if_trait; export get_item_attrs; export get_crate_module_paths; @@ -164,6 +166,13 @@ fn item_family(item: ebml::Doc) -> Family { } } +fn item_method_sort(item: ebml::Doc) -> char { + for ebml::tagged_docs(item, tag_item_trait_method_sort) |doc| { + return str::from_bytes(ebml::doc_data(doc))[0] as char; + } + return 'r'; +} + fn item_symbol(item: ebml::Doc) -> ~str { let sym = ebml::get_doc(item, tag_items_data_item_symbol); return str::from_bytes(ebml::doc_data(sym)); @@ -701,6 +710,7 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, let bounds = item_ty_param_bounds(mth, tcx, cdata); let name = item_name(intr, mth); let ty = doc_type(mth, tcx, cdata); + let def_id = item_def_id(mth, cdata); let fty = match ty::get(ty).sty { ty::ty_fn(f) => f, _ => { @@ -708,14 +718,52 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, ~"get_trait_methods: id has non-function type"); } }; let self_ty = get_self_ty(mth); - result.push({ident: name, tps: bounds, fty: fty, - self_ty: self_ty, - vis: ast::public}); + result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty, + vis: ast::public, def_id: def_id}); } debug!("get_trait_methods: }"); @result } +fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, + id: ast::node_id, tcx: ty::ctxt) -> + ~[ProvidedTraitMethodInfo] { + let data = cdata.data; + let item = lookup_item(id, data); + let mut result = ~[]; + + for ebml::tagged_docs(item, tag_item_trait_method) |mth| { + if item_method_sort(mth) != 'p' { loop; } + + let did = item_def_id(mth, cdata); + + let bounds = item_ty_param_bounds(mth, tcx, cdata); + let name = item_name(intr, mth); + let ty = doc_type(mth, tcx, cdata); + + let fty; + match ty::get(ty).sty { + ty::ty_fn(f) => fty = f, + _ => { + tcx.diag.handler().bug(~"get_provided_trait_methods(): id \ + has non-function type"); + } + } + + let self_ty = get_self_ty(mth); + let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty, + vis: ast::public, def_id: did}; + let provided_trait_method_info = ProvidedTraitMethodInfo { + ty: ty_method, + def_id: did + }; + + vec::push(&mut result, move provided_trait_method_info); + } + + return move result; +} + // If the item in question is a trait, returns its set of methods and // their self types. Otherwise, returns none. This overlaps in an // annoying way with get_trait_methods. diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 2fdd39a2ca48..652af81659a0 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -388,6 +388,12 @@ fn encode_self_type(ebml_w: ebml::Serializer, self_type: ast::self_ty_) { ebml_w.end_tag(); } +fn encode_method_sort(ebml_w: ebml::Serializer, sort: char) { + ebml_w.start_tag(tag_item_trait_method_sort); + ebml_w.writer.write(&[ sort as u8 ]); + ebml_w.end_tag(); +} + /* Returns an index of items in this class */ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Serializer, id: node_id, path: ast_map::path, @@ -726,6 +732,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, } } item_trait(tps, traits, ms) => { + let provided_methods = dvec::DVec(); + add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); @@ -746,12 +754,21 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty)); encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); encode_self_type(ebml_w, mty.self_ty); + encode_method_sort(ebml_w, 'r'); ebml_w.end_tag(); } provided(m) => { - encode_info_for_method(ecx, ebml_w, path, - should_inline(m.attrs), item.id, - m, m.tps); + provided_methods.push(m); + + ebml_w.start_tag(tag_item_trait_method); + encode_def_id(ebml_w, local_def(m.id)); + encode_name(ecx, ebml_w, mty.ident); + encode_type_param_bounds(ebml_w, ecx, m.tps); + encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty)); + encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); + encode_self_type(ebml_w, mty.self_ty); + encode_method_sort(ebml_w, 'p'); + ebml_w.end_tag(); } } i += 1u; @@ -785,7 +802,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, ebml_w.end_tag(); } - + // Finally, output all the provided methods as items. + for provided_methods.each |m| { + index.push({val: m.id, pos: ebml_w.writer.tell()}); + encode_info_for_method(ecx, ebml_w, path, true, item.id, *m, + m.tps); + } } item_mac(*) => fail ~"item macros unimplemented" } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index ba8e6c26274a..4f170fd050be 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -4680,6 +4680,9 @@ impl Resolver { } fn search_for_traits_containing_method(name: ident) -> @DVec { + debug!("(searching for traits containing method) looking for '%s'", + self.session.str_of(name)); + let found_traits = @DVec(); let mut search_module = self.current_module; loop { @@ -4687,8 +4690,8 @@ impl Resolver { match copy self.current_trait_refs { Some(trait_def_ids) => { for trait_def_ids.each |trait_def_id| { - self.add_trait_info_if_containing_method - (found_traits, *trait_def_id, name); + self.add_trait_info_if_containing_method( + found_traits, *trait_def_id, name); } } None => { @@ -4702,8 +4705,8 @@ impl Resolver { Some(def) => { match def.def { def_ty(trait_def_id) => { - self.add_trait_info_if_containing_method - (found_traits, trait_def_id, name); + self.add_trait_info_if_containing_method( + found_traits, trait_def_id, name); } _ => { // Continue. @@ -4730,8 +4733,8 @@ impl Resolver { match def.def { def_ty(trait_def_id) => { self. - add_trait_info_if_containing_method - (found_traits, trait_def_id, name); + add_trait_info_if_containing_method( + found_traits, trait_def_id, name); } _ => { // Continue. @@ -4766,6 +4769,12 @@ impl Resolver { trait_def_id: def_id, name: ident) { + debug!("(adding trait info if containing method) trying trait %d:%d \ + for method '%s'", + trait_def_id.crate, + trait_def_id.node, + self.session.str_of(name)); + match self.trait_info.find(trait_def_id) { Some(trait_info) if trait_info.contains_key(name) => { debug!("(adding trait info if containing method) found trait \ diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 06d5b2f239e3..93e8435d3e95 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -206,7 +206,7 @@ fn GEP_enum(bcx: block, llblobptr: ValueRef, enum_id: ast::def_id, assert ix < variant.args.len(); let arg_lltys = vec::map(variant.args, |aty| { - type_of(ccx, ty::subst_tps(ccx.tcx, ty_substs, *aty)) + type_of(ccx, ty::subst_tps(ccx.tcx, ty_substs, None, *aty)) }); let typed_blobptr = PointerCast(bcx, llblobptr, T_ptr(T_struct(arg_lltys))); @@ -385,16 +385,16 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, let _icx = ccx.insn_ctxt("trans_res_dtor"); if (substs.is_not_empty()) { let did = if did.crate != ast::local_crate { - inline::maybe_instantiate_inline(ccx, did) + inline::maybe_instantiate_inline(ccx, did, true) } else { did }; assert did.crate == ast::local_crate; - monomorphize::monomorphic_fn(ccx, did, substs, None, None).val + monomorphize::monomorphic_fn(ccx, did, substs, None, None, None).val } else if did.crate == ast::local_crate { get_item_val(ccx, did.node) } else { let tcx = ccx.tcx; let name = csearch::get_symbol(ccx.sess.cstore, did); - let class_ty = ty::subst_tps(tcx, substs, + let class_ty = ty::subst_tps(tcx, substs, None, ty::lookup_item_type(tcx, parent_id).ty); let llty = type_of_dtor(ccx, class_ty); get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv, @@ -529,7 +529,8 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, let v_id = variant.id; for vec::each(fn_ty.sig.inputs) |a| { let llfldp_a = GEP_enum(cx, a_tup, tid, v_id, tps, j); - let ty_subst = ty::subst_tps(ccx.tcx, tps, a.ty); + // XXX: Is "None" right here? + let ty_subst = ty::subst_tps(ccx.tcx, tps, None, a.ty); cx = f(cx, llfldp_a, ty_subst); j += 1u; } @@ -1392,8 +1393,11 @@ fn mk_standard_basic_blocks(llfn: ValueRef) -> // - create_llargs_for_fn_args. // - new_fn_ctxt // - trans_args -fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path, - llfndecl: ValueRef, id: ast::node_id, +fn new_fn_ctxt_w_id(ccx: @crate_ctxt, + path: path, + llfndecl: ValueRef, + id: ast::node_id, + impl_id: Option, param_substs: Option, sp: Option) -> fn_ctxt { let llbbs = mk_standard_basic_blocks(llfndecl); @@ -1410,6 +1414,7 @@ fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path, lllocals: HashMap(), llupvars: HashMap(), id: id, + impl_id: impl_id, param_substs: param_substs, span: sp, path: path, @@ -1418,7 +1423,7 @@ fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path, fn new_fn_ctxt(ccx: @crate_ctxt, path: path, llfndecl: ValueRef, sp: Option) -> fn_ctxt { - return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, sp); + return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, None, sp); } // NB: must keep 4 fns in sync: @@ -1561,6 +1566,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, ty_self: self_arg, param_substs: Option, id: ast::node_id, + impl_id: Option, maybe_load_env: fn(fn_ctxt), finish: fn(block)) { ccx.stats.n_closures += 1; @@ -1568,7 +1574,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, set_uwtable(llfndecl); // Set up arguments to the function. - let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, param_substs, + let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, impl_id, param_substs, Some(body.span)); let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, decl.inputs); @@ -1620,14 +1626,15 @@ fn trans_fn(ccx: @crate_ctxt, llfndecl: ValueRef, ty_self: self_arg, param_substs: Option, - id: ast::node_id) { + id: ast::node_id, + impl_id: Option) { let do_time = ccx.sess.trans_stats(); let start = if do_time { time::get_time() } else { {sec: 0i64, nsec: 0i32} }; let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; trans_closure(ccx, path, decl, body, llfndecl, ty_self, - param_substs, id, + param_substs, id, impl_id, |fcx| { if ccx.sess.opts.extra_debuginfo { debuginfo::create_function(fcx); @@ -1654,7 +1661,7 @@ fn trans_enum_variant(ccx: @crate_ctxt, ty: varg.ty, ident: special_idents::arg, id: varg.id}); - let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, + let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, None, param_substs, None); let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); let ty_param_substs = match param_substs { @@ -1704,7 +1711,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path, let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty; /* Substitute in the class type if necessary */ do option::iter(&psubsts) |ss| { - class_ty = ty::subst_tps(tcx, ss.tys, class_ty); + class_ty = ty::subst_tps(tcx, ss.tys, ss.self_ty, class_ty); } /* The dtor takes a (null) output pointer, and a self argument, @@ -1724,7 +1731,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path, } /* Translate the dtor body */ trans_fn(ccx, path, ast_util::dtor_dec(), - body, lldecl, impl_self(class_ty), psubsts, dtor_id); + body, lldecl, impl_self(class_ty), psubsts, dtor_id, None); lldecl } @@ -1777,7 +1784,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, vec::append(*path, ~[path_name(item.ident)]), - decl, body, llfndecl, no_self, None, item.id); + decl, body, llfndecl, no_self, None, item.id, None); } else { for vec::each(body.node.stmts) |stmt| { match stmt.node { @@ -1789,48 +1796,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { } } } - ast::item_impl(tps, trait_refs, self_ast_ty, ms) => { - meth::trans_impl(ccx, *path, item.ident, ms, tps, None); - - // Translate any methods that have provided implementations. - for trait_refs.each |trait_ref_ptr| { - let trait_def = ccx.tcx.def_map.get(trait_ref_ptr.ref_id); - - // XXX: Cross-crate default methods. - let trait_id = def_id_of_def(trait_def); - if trait_id.crate != ast::local_crate { - loop; - } - - // Get the self type. - let self_ty; - match ccx.tcx.ast_ty_to_ty_cache.get(self_ast_ty) { - ty::atttce_resolved(self_type) => self_ty = self_type, - ty::atttce_unresolved => { - ccx.tcx.sess.impossible_case(item.span, - ~"didn't cache self ast ty"); - } - } - - match ccx.tcx.items.get(trait_id.node) { - ast_map::node_item(trait_item, _) => { - match trait_item.node { - ast::item_trait(tps, _, trait_methods) => { - trans_trait(ccx, tps, trait_methods, path, - item.ident, self_ty); - } - _ => { - ccx.tcx.sess.impossible_case(item.span, - ~"trait item not a \ - trait"); - } - } - } - _ => { - ccx.tcx.sess.impossible_case(item.span, ~"no trait item"); - } - } - } + ast::item_impl(tps, _, _, ms) => { + meth::trans_impl(ccx, *path, item.ident, ms, tps, None, item.id); } ast::item_mod(m) => { trans_mod(ccx, m); @@ -1871,16 +1838,7 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, // If there are ty params, the ctor will get monomorphized // Translate methods - meth::trans_impl(ccx, *path, ident, struct_def.methods, tps, None); -} - -fn trans_trait(ccx: @crate_ctxt, tps: ~[ast::ty_param], - trait_methods: ~[ast::trait_method], - path: @ast_map::path, ident: ast::ident, - self_ty: ty::t) { - // Translate any methods that have provided implementations - let (_, provided_methods) = ast_util::split_trait_methods(trait_methods); - meth::trans_impl(ccx, *path, ident, provided_methods, tps, Some(self_ty)); + meth::trans_impl(ccx, *path, ident, struct_def.methods, tps, None, id); } // Translate a module. Doing this amounts to translating the items in the @@ -2035,7 +1993,7 @@ fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id, // this to item_symbols match substs { Some(ss) => { - let mono_ty = ty::subst_tps(ccx.tcx, ss.tys, t); + let mono_ty = ty::subst_tps(ccx.tcx, ss.tys, ss.self_ty, t); mangle_exported_name( ccx, vec::append(path, diff --git a/src/rustc/middle/trans/callee.rs b/src/rustc/middle/trans/callee.rs index aa998fb7b92d..133f4647e683 100644 --- a/src/rustc/middle/trans/callee.rs +++ b/src/rustc/middle/trans/callee.rs @@ -184,21 +184,31 @@ fn trans_fn_ref_with_vtables( // Polytype of the function item (may have type params) let fn_tpt = ty::lookup_item_type(tcx, def_id); + // Modify the def_id if this is a default method; we want to be + // monomorphizing the trait's code. + let (def_id, opt_impl_did) = + match tcx.provided_method_sources.find(def_id) { + None => (def_id, None), + Some(source) => (source.method_id, Some(source.impl_id)) + }; + // Check whether this fn has an inlined copy and, if so, redirect // def_id to the local id of the inlined copy. let def_id = { if def_id.crate != ast::local_crate { - inline::maybe_instantiate_inline(ccx, def_id) + let may_translate = opt_impl_did.is_none(); + inline::maybe_instantiate_inline(ccx, def_id, may_translate) } else { def_id } }; - // We must monomorphise if the fn has type parameters or is a rust - // intrinsic. In particular, if we see an intrinsic that is - // inlined from a different crate, we want to reemit the intrinsic - // instead of trying to call it in the other crate. - let must_monomorphise = type_params.len() > 0 || { + // We must monomorphise if the fn has type parameters, is a rust + // intrinsic, or is a default method. In particular, if we see an + // intrinsic that is inlined from a different crate, we want to reemit the + // intrinsic instead of trying to call it in the other crate. + let must_monomorphise = type_params.len() > 0 || + opt_impl_did.is_some() || { if def_id.crate == ast::local_crate { let map_node = session::expect( ccx.sess, @@ -222,7 +232,7 @@ fn trans_fn_ref_with_vtables( let mut {val, must_cast} = monomorphize::monomorphic_fn(ccx, def_id, type_params, - vtables, Some(ref_id)); + vtables, opt_impl_did, Some(ref_id)); if must_cast && ref_id != 0 { // Monotype of the REFERENCE to the function (type params // are subst'd) @@ -317,7 +327,9 @@ fn trans_rtcall_or_lang_call_with_type_params(bcx: block, match callee.data { Fn(fn_data) => { let substituted = ty::subst_tps(callee.bcx.tcx(), - type_params, fty); + type_params, + None, + fty); let mut llfnty = type_of::type_of(callee.bcx.ccx(), substituted); llfnty = T_ptr(struct_elt(llfnty, 0)); diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 655efe75bf65..3997076f9871 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -372,7 +372,7 @@ fn trans_expr_fn(bcx: block, let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, ret_handle); trans_closure(ccx, sub_path, decl, body, llfn, no_self, - bcx.fcx.param_substs, id, |fcx| { + bcx.fcx.param_substs, id, None, |fcx| { load_environment(fcx, cdata_ty, cap_vars, ret_handle.is_some(), ck); }, |bcx| { @@ -395,7 +395,7 @@ fn trans_expr_fn(bcx: block, } ty::proto_bare => { trans_closure(ccx, sub_path, decl, body, llfn, no_self, None, - id, |_fcx| { }, |_bcx| { }); + id, None, |_fcx| { }, |_bcx| { }); rslt(bcx, C_null(T_opaque_box_ptr(ccx))) } ty::proto_vstore(ty::vstore_fixed(_)) => { diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 61141f18336f..0fa22dd65ba7 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -181,9 +181,12 @@ struct ValSelfData { enum local_val { local_mem(ValueRef), local_imm(ValueRef), } +// Here `self_ty` is the real type of the self parameter to this method. It +// will only be set in the case of default methods. type param_substs = {tys: ~[ty::t], vtables: Option, - bounds: @~[ty::param_bounds]}; + bounds: @~[ty::param_bounds], + self_ty: Option}; fn param_substs_to_str(tcx: ty::ctxt, substs: ¶m_substs) -> ~str { fmt!("param_substs {tys:%?, vtables:%?, bounds:%?}", @@ -220,6 +223,10 @@ type fn_ctxt = @{ mut llreturn: BasicBlockRef, // The 'self' value currently in use in this function, if there // is one. + // + // NB: This is the type of the self *variable*, not the self *type*. The + // self type is set only for default methods, while the self variable is + // set for all methods. mut llself: Option, // The a value alloca'd for calls to upcalls.rust_personality. Used when // outputting the resume instruction. @@ -240,6 +247,9 @@ type fn_ctxt = @{ // a user-defined function. id: ast::node_id, + // The def_id of the impl we're inside, or None if we aren't inside one. + impl_id: Option, + // If this function is being monomorphized, this contains the type // substitutions used. param_substs: Option, @@ -1110,7 +1120,11 @@ enum mono_param_id { datum::DatumMode), } -type mono_id_ = {def: ast::def_id, params: ~[mono_param_id]}; +type mono_id_ = { + def: ast::def_id, + params: ~[mono_param_id], + impl_did_opt: Option +}; type mono_id = @mono_id_; @@ -1193,7 +1207,9 @@ fn path_str(sess: session::session, p: path) -> ~str { fn monomorphize_type(bcx: block, t: ty::t) -> ty::t { match bcx.fcx.param_substs { - Some(substs) => ty::subst_tps(bcx.tcx(), substs.tys, t), + Some(substs) => { + ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t) + } _ => { assert !ty::type_has_params(t); t } } } @@ -1213,7 +1229,9 @@ fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] { let params = ty::node_id_to_type_params(tcx, id); match bcx.fcx.param_substs { Some(substs) => { - vec::map(params, |t| ty::subst_tps(tcx, substs.tys, *t)) + do vec::map(params) |t| { + ty::subst_tps(tcx, substs.tys, substs.self_ty, *t) + } } _ => params } @@ -1241,7 +1259,9 @@ fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin) typeck::vtable_static(trait_id, tys, sub) => { let tys = match fcx.param_substs { Some(substs) => { - vec::map(tys, |t| ty::subst_tps(tcx, substs.tys, *t)) + do vec::map(tys) |t| { + ty::subst_tps(tcx, substs.tys, substs.self_ty, *t) + } } _ => tys }; diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 333d76a91ee6..08abe986be6f 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -793,7 +793,9 @@ fn trans_local_var(bcx: block, def: ast::def) -> Datum { // This cast should not be necessary. We should cast self *once*, // but right now this conflicts with default methods. - let llselfty = T_ptr(type_of::type_of(bcx.ccx(), self_info.t)); + let real_self_ty = monomorphize_type(bcx, self_info.t); + let llselfty = T_ptr(type_of::type_of(bcx.ccx(), real_self_ty)); + let casted_val = PointerCast(bcx, self_info.v, llselfty); Datum { val: casted_val, diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index dbf5ef810462..5a6260ae2700 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -794,7 +794,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, { debug!("trans_intrinsic(item.ident=%s)", ccx.sess.str_of(item.ident)); - let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, + let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, None, Some(substs), Some(item.span)); let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb; match ccx.sess.str_of(item.ident) { @@ -1025,7 +1025,7 @@ fn trans_foreign_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl, ))); let llty = type_of_fn_from_ty(ccx, t); let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty); - trans_fn(ccx, path, decl, body, llfndecl, no_self, None, id); + trans_fn(ccx, path, decl, body, llfndecl, no_self, None, id, None); return llfndecl; } diff --git a/src/rustc/middle/trans/inline.rs b/src/rustc/middle/trans/inline.rs index ce9088d4b55c..d3cc23094ee8 100644 --- a/src/rustc/middle/trans/inline.rs +++ b/src/rustc/middle/trans/inline.rs @@ -5,9 +5,12 @@ use syntax::ast_map::{path, path_mod, path_name}; use base::{trans_item, get_item_val, self_arg, trans_fn, impl_self, get_insn_ctxt}; -fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) - -> ast::def_id -{ +// `translate` will be true if this function is allowed to translate the +// item and false otherwise. Currently, this parameter is set to false when +// translating default methods. +fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, + translate: bool) + -> ast::def_id { let _icx = ccx.insn_ctxt("maybe_instantiate_inline"); match ccx.external.find(fn_id) { Some(Some(node_id)) => { @@ -31,7 +34,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) csearch::found(ast::ii_item(item)) => { ccx.external.insert(fn_id, Some(item.id)); ccx.stats.n_inlines += 1; - trans_item(ccx, *item); + if translate { trans_item(ccx, *item); } local_def(item.id) } csearch::found(ast::ii_foreign(item)) => { @@ -53,7 +56,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) _ => ccx.sess.bug(~"maybe_instantiate_inline: item has a \ non-enum parent") } - trans_item(ccx, *item); + if translate { trans_item(ccx, *item); } local_def(my_id) } csearch::found_parent(_, _) => { @@ -65,13 +68,14 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) ccx.external.insert(fn_id, Some(mth.id)); let {bounds: impl_bnds, region_param: _, ty: impl_ty} = ty::lookup_item_type(ccx.tcx, impl_did); - if (*impl_bnds).len() + mth.tps.len() == 0u { + if translate && (*impl_bnds).len() + mth.tps.len() == 0u { let llfn = get_item_val(ccx, mth.id); let path = vec::append( ty::item_path(ccx.tcx, impl_did), ~[path_name(mth.ident)]); trans_fn(ccx, path, mth.decl, mth.body, - llfn, impl_self(impl_ty), None, mth.id); + llfn, impl_self(impl_ty), None, mth.id, + Some(impl_did)); } local_def(mth.id) } @@ -83,3 +87,4 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) } } } + diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs index 96cf7fabd1f7..89b101ab8759 100644 --- a/src/rustc/middle/trans/meth.rs +++ b/src/rustc/middle/trans/meth.rs @@ -28,7 +28,7 @@ see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. */ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident, methods: ~[@ast::method], tps: ~[ast::ty_param], - self_ty: Option) { + self_ty: Option, id: ast::node_id) { let _icx = ccx.insn_ctxt("impl::trans_impl"); if tps.len() > 0u { return; } let sub_path = vec::append_one(path, path_name(name)); @@ -36,7 +36,22 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident, if method.tps.len() == 0u { let llfn = get_item_val(ccx, method.id); let path = vec::append_one(sub_path, path_name(method.ident)); - trans_method(ccx, path, *method, None, self_ty, llfn); + + let param_substs_opt; + match self_ty { + None => param_substs_opt = None, + Some(self_ty) => { + param_substs_opt = Some({ + tys: ~[], + vtables: None, + bounds: @~[], + self_ty: Some(self_ty) + }); + } + } + + trans_method(ccx, path, *method, param_substs_opt, self_ty, llfn, + ast_util::local_def(id)); } } } @@ -54,13 +69,15 @@ Translates a (possibly monomorphized) method body. will be none if this is not a default method and must always be present if this is a default method. - `llfn`: the LLVM ValueRef for the method +- `impl_id`: the node ID of the impl this method is inside */ fn trans_method(ccx: @crate_ctxt, path: path, method: &ast::method, param_substs: Option, base_self_ty: Option, - llfn: ValueRef) { + llfn: ValueRef, + impl_id: ast::def_id) { // figure out how self is being passed let self_arg = match method.self_ty.node { @@ -76,8 +93,10 @@ fn trans_method(ccx: @crate_ctxt, Some(provided_self_ty) => self_ty = provided_self_ty } let self_ty = match param_substs { - None => self_ty, - Some({tys: ref tys, _}) => ty::subst_tps(ccx.tcx, *tys, self_ty) + None => self_ty, + Some({tys: ref tys, _}) => { + ty::subst_tps(ccx.tcx, *tys, None, self_ty) + } }; match method.self_ty.node { ast::sty_value => { @@ -98,15 +117,20 @@ fn trans_method(ccx: @crate_ctxt, llfn, self_arg, param_substs, - method.id); + method.id, + Some(impl_id)); } -fn trans_self_arg(bcx: block, base: @ast::expr, +fn trans_self_arg(bcx: block, + base: @ast::expr, mentry: typeck::method_map_entry) -> Result { let _icx = bcx.insn_ctxt("impl::trans_self_arg"); let mut temp_cleanups = ~[]; + + // Compute the mode and type of self. let self_arg = {mode: mentry.self_arg.mode, ty: monomorphize_type(bcx, mentry.self_arg.ty)}; + let result = trans_arg_expr(bcx, self_arg, base, &mut temp_cleanups, None, DontAutorefArg); @@ -120,11 +144,31 @@ fn trans_self_arg(bcx: block, base: @ast::expr, } fn trans_method_callee(bcx: block, callee_id: ast::node_id, - self: @ast::expr, mentry: typeck::method_map_entry) - -> Callee -{ + self: @ast::expr, mentry: typeck::method_map_entry) -> + Callee { let _icx = bcx.insn_ctxt("impl::trans_method_callee"); - match mentry.origin { + + // Replace method_self with method_static here. + let mut origin = mentry.origin; + match origin { + typeck::method_self(copy trait_id, copy method_index) => { + // Get the ID of the impl we're inside. + let impl_def_id = bcx.fcx.impl_id.get(); + + io::println(fmt!("impl_def_id is %?", impl_def_id)); + + // Get the ID of the method we're calling. + let method_name = + ty::trait_methods(bcx.tcx(), trait_id)[method_index].ident; + let method_id = method_with_name(bcx.ccx(), impl_def_id, + method_name); + origin = typeck::method_static(method_id); + } + typeck::method_static(*) | typeck::method_param(*) | + typeck::method_trait(*) => {} + } + + match origin { typeck::method_static(did) => { let callee_fn = callee::trans_fn_ref(bcx, did, callee_id); let Result {bcx, val} = trans_self_arg(bcx, self, mentry); @@ -155,7 +199,7 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id, trans_trait_callee(bcx, callee_id, off, self, vstore) } typeck::method_self(*) => { - bcx.tcx().sess.span_bug(self.span, ~"self method call"); + fail ~"method_self should have been handled above" } } } @@ -519,13 +563,21 @@ fn vtable_id(ccx: @crate_ctxt, origin: typeck::vtable_origin) -> mono_id { match origin { typeck::vtable_static(impl_id, substs, sub_vtables) => { monomorphize::make_mono_id( - ccx, impl_id, substs, - if (*sub_vtables).len() == 0u { None } - else { Some(sub_vtables) }, None) + ccx, + impl_id, + substs, + if (*sub_vtables).len() == 0u { + None + } else { + Some(sub_vtables) + }, + None, + None) } typeck::vtable_trait(trait_id, substs) => { @{def: trait_id, - params: vec::map(substs, |t| mono_precise(*t, None))} + params: vec::map(substs, |t| mono_precise(*t, None)), + impl_did_opt: None} } // can't this be checked at the callee? _ => fail ~"vtable_id" @@ -571,7 +623,7 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t], let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u; make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| { - let fty = ty::subst_tps(tcx, substs, ty::mk_fn(tcx, im.fty)); + let fty = ty::subst_tps(tcx, substs, None, ty::mk_fn(tcx, im.fty)); if (*im.tps).len() > 0u || ty::type_has_self(fty) { C_null(T_ptr(T_nil())) } else { @@ -580,10 +632,11 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t], // If the method is in another crate, need to make an inlined // copy first if m_id.crate != ast::local_crate { - m_id = inline::maybe_instantiate_inline(ccx, m_id); + // XXX: Set impl ID here? + m_id = inline::maybe_instantiate_inline(ccx, m_id, true); } monomorphize::monomorphic_fn(ccx, m_id, substs, - Some(vtables), None).val + Some(vtables), None, None).val } else if m_id.crate == ast::local_crate { get_item_val(ccx, m_id.node) } else { diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 914b733df198..f6763206e18c 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -16,9 +16,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: ~[ty::t], vtables: Option, - ref_id: Option) - -> {val: ValueRef, must_cast: bool} -{ + impl_did_opt: Option, + ref_id: Option) -> + {val: ValueRef, must_cast: bool} { let _icx = ccx.insn_ctxt("monomorphic_fn"); let mut must_cast = false; let substs = vec::map(real_substs, |t| { @@ -31,7 +31,8 @@ fn monomorphic_fn(ccx: @crate_ctxt, for real_substs.each() |s| { assert !ty::type_has_params(*s); } for substs.each() |s| { assert !ty::type_has_params(*s); } let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len()); - let hash_id = make_mono_id(ccx, fn_id, substs, vtables, Some(param_uses)); + let hash_id = make_mono_id(ccx, fn_id, substs, vtables, impl_did_opt, + Some(param_uses)); if vec::any(hash_id.params, |p| match *p { mono_precise(_, _) => false, _ => true }) { must_cast = true; @@ -73,8 +74,11 @@ fn monomorphic_fn(ccx: @crate_ctxt, } ast_map::node_dtor(_, dtor, _, pt) => (pt, special_idents::dtor, dtor.span), - ast_map::node_trait_method(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize a trait method") + ast_map::node_trait_method(@ast::provided(m), _, pt) => { + (pt, m.ident, m.span) + } + ast_map::node_trait_method(@ast::required(_), _, _) => { + ccx.tcx.sess.bug(~"Can't monomorphize a required trait method") } ast_map::node_expr(*) => { ccx.tcx.sess.bug(~"Can't monomorphize an expr") @@ -93,7 +97,18 @@ fn monomorphic_fn(ccx: @crate_ctxt, ccx.tcx.sess.bug(~"Can't monomorphize a local") } }; - let mono_ty = ty::subst_tps(ccx.tcx, substs, llitem_ty); + + // Look up the impl type if we're translating a default method. + // XXX: Generics. + let impl_ty_opt; + match impl_did_opt { + None => impl_ty_opt = None, + Some(impl_did) => { + impl_ty_opt = Some(ty::lookup_item_type(ccx.tcx, impl_did).ty); + } + } + + let mono_ty = ty::subst_tps(ccx.tcx, substs, impl_ty_opt, llitem_ty); let llfty = type_of_fn_from_ty(ccx, mono_ty); ccx.stats.n_monos += 1; @@ -118,12 +133,18 @@ fn monomorphic_fn(ccx: @crate_ctxt, lldecl }; - let psubsts = Some({tys: substs, vtables: vtables, bounds: tpt.bounds}); + let psubsts = Some({ + tys: substs, + vtables: vtables, + bounds: tpt.bounds, + self_ty: impl_ty_opt + }); + let lldecl = match map_node { ast_map::node_item(i@@{node: ast::item_fn(decl, _, _, body), _}, _) => { let d = mk_lldecl(); set_inline_hint_if_appr(i.attrs, d); - trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node); + trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None); d } ast_map::node_item(*) => { @@ -154,11 +175,19 @@ fn monomorphic_fn(ccx: @crate_ctxt, } d } - ast_map::node_method(mth, _, _) => { + ast_map::node_method(mth, supplied_impl_did, _) => { // XXX: What should the self type be here? let d = mk_lldecl(); set_inline_hint_if_appr(mth.attrs, d); - meth::trans_method(ccx, pt, mth, psubsts, None, d); + + // Override the impl def ID if necessary. + let impl_did; + match impl_did_opt { + None => impl_did = supplied_impl_did, + Some(override_impl_did) => impl_did = override_impl_did + } + + meth::trans_method(ccx, pt, mth, psubsts, None, d, impl_did); d } ast_map::node_dtor(_, dtor, _, pt) => { @@ -171,6 +200,15 @@ fn monomorphic_fn(ccx: @crate_ctxt, trans_class_dtor(ccx, *pt, dtor.node.body, dtor.node.id, psubsts, Some(hash_id), parent_id) } + ast_map::node_trait_method(@ast::provided(mth), _, pt) => { + let d = mk_lldecl(); + set_inline_hint_if_appr(mth.attrs, d); + io::println(fmt!("monomorphic_fn impl_did_opt is %?", impl_did_opt)); + meth::trans_method(ccx, *pt, mth, psubsts, None, d, + impl_did_opt.get()); + d + } + // Ugh -- but this ensures any new variants won't be forgotten ast_map::node_expr(*) | ast_map::node_stmt(*) | @@ -226,6 +264,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option { fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], vtables: Option, + impl_did_opt: Option, param_uses: Option<~[type_use::type_uses]>) -> mono_id { let precise_param_ids = match vtables { Some(vts) => { @@ -295,5 +334,5 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], }) } }; - @{def: item, params: param_ids} + @{def: item, params: param_ids, impl_did_opt: impl_did_opt} } diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 1f9ad20dd03e..8ccc8a28de3a 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -40,8 +40,13 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) Some(uses) => return uses, None => () } - let fn_id_loc = if fn_id.crate == local_crate { fn_id } - else { inline::maybe_instantiate_inline(ccx, fn_id) }; + + let fn_id_loc = if fn_id.crate == local_crate { + fn_id + } else { + inline::maybe_instantiate_inline(ccx, fn_id, true) + }; + // Conservatively assume full use for recursive loops ccx.type_use_cache.insert(fn_id, vec::from_elem(n_tps, 3u)); diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index cc132a431a33..a0ca46ee0178 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -19,6 +19,7 @@ use syntax::ast::*; use syntax::print::pprust::*; use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str}; +export ProvidedMethodSource; export TyVid, IntVid, FnVid, RegionVid, vid; export br_hashmap; export is_instantiable; @@ -207,7 +208,8 @@ type method = {ident: ast::ident, tps: @~[param_bounds], fty: FnTy, self_ty: ast::self_ty_, - vis: ast::visibility}; + vis: ast::visibility, + def_id: ast::def_id}; type mt = {ty: t, mutbl: ast::mutability}; @@ -314,6 +316,11 @@ enum AutoRefKind { AutoPtr } +struct ProvidedMethodSource { + method_id: ast::def_id, + impl_id: ast::def_id +} + type ctxt = @{diag: syntax::diagnostic::span_handler, interner: HashMap, @@ -356,7 +363,8 @@ type ctxt = adjustments: HashMap, normalized_cache: HashMap, lang_items: middle::lang_items::LanguageItems, - legacy_boxed_traits: HashMap}; + legacy_boxed_traits: HashMap, + provided_method_sources: HashMap}; enum tbox_flag { has_params = 1, @@ -879,7 +887,8 @@ fn mk_ctxt(s: session::session, adjustments: HashMap(), normalized_cache: new_ty_hash(), lang_items: move lang_items, - legacy_boxed_traits: HashMap()} + legacy_boxed_traits: HashMap(), + provided_method_sources: HashMap()} } @@ -1392,13 +1401,23 @@ fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t { } // Substitute *only* type parameters. Used in trans where regions are erased. -fn subst_tps(cx: ctxt, tps: &[t], typ: t) -> t { - if tps.len() == 0u { return typ; } +fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option, typ: t) -> t { + if tps.len() == 0u && self_ty_opt.is_none() { return typ; } let tb = ty::get(typ); - if !tbox_has_flag(tb, has_params) { return typ; } + if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; } match tb.sty { - ty_param(p) => tps[p.idx], - ref sty => fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, t)) + ty_param(p) => tps[p.idx], + ty_self => { + match self_ty_opt { + None => cx.sess.bug(~"ty_self unexpected here"), + Some(self_ty) => { + subst_tps(cx, tps, self_ty_opt, self_ty) + } + } + } + ref sty => { + fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, self_ty_opt, t)) + } } } @@ -3328,20 +3347,18 @@ fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) { cx.trait_method_cache.insert(ast_util::local_def(id), ms); } -fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@ast::method] { +fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] { if is_local(id) { match cx.items.find(id.node) { Some(ast_map::node_item(@{node: item_trait(_, _, ms),_}, _)) => match ast_util::split_trait_methods(ms) { - (_, p) => p + (_, p) => p.map(|method| method.ident) }, _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait", id)) } - } - else { - // FIXME #2794: default methods for traits don't work cross-crate - ~[] + } else { + csearch::get_provided_trait_methods(cx, id).map(|info| info.ty.ident) } } @@ -3599,10 +3616,12 @@ fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id, // the type cache. Returns the type parameters and type. fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty { match cx.tcache.find(did) { - Some(tpt) => return tpt, - None => { + Some(tpt) => { // The item is in this crate. The caller should have added it to the // type cache already + return tpt; + } + None => { assert did.crate != ast::local_crate; let tyt = csearch::get_type(cx, did); cx.tcache.insert(did, tyt); diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 7cb04bc0ea3c..077d34700b8d 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -62,6 +62,7 @@ use util::ppaux::{ty_to_str, tys_to_str, region_to_str, use util::common::{indent, indenter}; use std::list; use list::{List, Nil, Cons}; +use dvec::DVec; export check_crate; export infer; @@ -174,12 +175,6 @@ impl vtable_origin { type vtable_map = HashMap; -// Stores information about provided methods, aka "default methods" in traits. -// Maps from a trait's def_id to a MethodInfo about -// that method in that trait. -type provided_methods_map = HashMap; - type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t}; type crate_ctxt_ = {// A mapping from method call sites to traits that have @@ -188,7 +183,6 @@ type crate_ctxt_ = {// A mapping from method call sites to traits that have method_map: method_map, vtable_map: vtable_map, coherence_info: @coherence::CoherenceInfo, - provided_methods_map: provided_methods_map, tcx: ty::ctxt}; enum crate_ctxt { @@ -340,7 +334,6 @@ fn check_crate(tcx: ty::ctxt, method_map: std::map::HashMap(), vtable_map: std::map::HashMap(), coherence_info: @coherence::CoherenceInfo(), - provided_methods_map: std::map::HashMap(), tcx: tcx}); collect::collect_item_types(ccx, crate); coherence::check_coherence(ccx, crate); diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index 0d71d61bdaad..04be00475482 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -69,7 +69,7 @@ obtained the type `Foo`, we would never match this method. */ -use coherence::get_base_type_def_id; +use coherence::{ProvidedMethodInfo, get_base_type_def_id}; use middle::resolve::{Impl, MethodInfo}; use middle::ty::*; use syntax::ast::{def_id, sty_by_ref, sty_value, sty_region, sty_box, @@ -146,7 +146,7 @@ impl LookupContext { // Prepare the list of candidates self.push_inherent_candidates(self_ty); - self.push_extension_candidates(); + self.push_extension_candidates(self_ty); let enum_dids = DVec(); let mut self_ty = self_ty; @@ -251,7 +251,7 @@ impl LookupContext { } } - fn push_extension_candidates(&self) { + fn push_extension_candidates(&self, self_ty: ty::t) { // If the method being called is associated with a trait, then // find all the impls of that trait. Each of those are // candidates. @@ -259,6 +259,8 @@ impl LookupContext { for opt_applicable_traits.each |applicable_traits| { for applicable_traits.each |trait_did| { let coherence_info = self.fcx.ccx.coherence_info; + + // Look for explicit implementations. let opt_impl_infos = coherence_info.extension_methods.find(*trait_did); for opt_impl_infos.each |impl_infos| { @@ -267,12 +269,21 @@ impl LookupContext { &self.extension_candidates, *impl_info); } } + + // Look for default methods. + match coherence_info.provided_methods.find(*trait_did) { + Some(methods) => { + self.push_candidates_from_provided_methods( + &self.extension_candidates, self_ty, *trait_did, + methods); + } + None => {} + } } } } - fn push_inherent_candidates_from_param(&self, param_ty: param_ty) - { + fn push_inherent_candidates_from_param(&self, param_ty: param_ty) { debug!("push_inherent_candidates_from_param(param_ty=%?)", param_ty); let _indenter = indenter(); @@ -348,8 +359,7 @@ impl LookupContext { self_ty: ty::t, did: def_id, substs: &ty::substs, - vstore: ty::vstore) - { + vstore: ty::vstore) { debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)", self.did_to_str(did), substs_to_str(self.tcx(), substs)); @@ -423,8 +433,7 @@ impl LookupContext { }); } - fn push_inherent_impl_candidates_for_type(did: def_id) - { + fn push_inherent_impl_candidates_for_type(did: def_id) { let opt_impl_infos = self.fcx.ccx.coherence_info.inherent_methods.find(did); for opt_impl_infos.each |impl_infos| { @@ -436,8 +445,7 @@ impl LookupContext { } fn push_candidates_from_impl(&self, candidates: &DVec, - impl_info: &resolve::Impl) - { + impl_info: &resolve::Impl) { if !self.impl_dups.insert(impl_info.did, ()) { return; // already visited } @@ -471,12 +479,47 @@ impl LookupContext { }); } + fn push_candidates_from_provided_methods( + &self, + candidates: &DVec, + self_ty: ty::t, + trait_def_id: def_id, + methods: @DVec<@ProvidedMethodInfo>) { + debug!("(pushing candidates from provided methods) considering trait \ + id %d:%d", + trait_def_id.crate, + trait_def_id.node); + + for methods.each |provided_method_info| { + if provided_method_info.method_info.ident != self.m_name { loop; } + + debug!("(pushing candidates from provided methods) adding \ + candidate"); + + // XXX: Needs to support generics. + let dummy_substs = { self_r: None, self_ty: None, tps: ~[] }; + let (impl_ty, impl_substs) = + self.create_rcvr_ty_and_substs_for_method( + provided_method_info.method_info.self_type, + self_ty, + dummy_substs); + + candidates.push(Candidate { + rcvr_ty: impl_ty, + rcvr_substs: move impl_substs, + num_method_tps: provided_method_info.method_info.n_tps, + self_mode: get_mode_from_self_type( + provided_method_info.method_info.self_type), + origin: method_static(provided_method_info.method_info.did) + }); + } + } + fn create_rcvr_ty_and_substs_for_method(&self, self_decl: ast::self_ty_, self_ty: ty::t, +self_substs: ty::substs) - -> (ty::t, ty::substs) - { + -> (ty::t, ty::substs) { // If the self type includes a region (like &self), we need to // ensure that the receiver substitutions have a self region. // If the receiver type does not itself contain borrowed @@ -693,8 +736,7 @@ impl LookupContext { fn confirm_candidate(&self, self_ty: ty::t, candidate: &Candidate) - -> method_map_entry - { + -> method_map_entry { let tcx = self.tcx(); let fty = self.fn_ty_from_origin(&candidate.origin); diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs index 00fb134f2be5..345b8246b427 100644 --- a/src/rustc/middle/typeck/check/vtable.rs +++ b/src/rustc/middle/typeck/check/vtable.rs @@ -444,7 +444,7 @@ fn connect_trait_tps(fcx: @fn_ctxt, expr: @ast::expr, impl_tys: ~[ty::t], // XXX: This should work for multiple traits. let ity = ty::impl_traits(tcx, impl_did, vstore)[0]; - let trait_ty = ty::subst_tps(tcx, impl_tys, ity); + let trait_ty = ty::subst_tps(tcx, impl_tys, None, ity); debug!("(connect trait tps) trait type is %?, impl did is %?", ty::get(trait_ty).sty, impl_did); match ty::get(trait_ty).sty { diff --git a/src/rustc/middle/typeck/coherence.rs b/src/rustc/middle/typeck/coherence.rs index 89cd696eb6fb..9a9a8dda6e4d 100644 --- a/src/rustc/middle/typeck/coherence.rs +++ b/src/rustc/middle/typeck/coherence.rs @@ -4,12 +4,13 @@ // has at most one implementation for each type. Then we build a mapping from // each trait in the system to its implementations. -use metadata::csearch::{each_path, get_impl_traits, get_impls_for_mod}; +use metadata::csearch::{ProvidedTraitMethodInfo, each_path, get_impl_traits}; +use metadata::csearch::{get_impls_for_mod}; use metadata::cstore::{cstore, iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use middle::resolve::{Impl, MethodInfo}; -use middle::ty::{get, lookup_item_type, subst, t, ty_box}; -use middle::ty::{ty_uniq, ty_ptr, ty_rptr, ty_enum}; +use middle::ty::{ProvidedMethodSource, get, lookup_item_type, subst, t}; +use middle::ty::{ty_box, ty_uniq, ty_ptr, ty_rptr, ty_enum}; use middle::ty::{ty_class, ty_nil, ty_bot, ty_bool, ty_int, ty_uint}; use middle::ty::{ty_float, ty_estr, ty_evec, ty_rec}; use middle::ty::{ty_fn, ty_trait, ty_tup, ty_infer}; @@ -17,7 +18,7 @@ use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box}; use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_is_ty_var}; use middle::typeck::infer::{infer_ctxt, can_mk_subty}; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type}; -use syntax::ast::{crate, def_id, def_mod}; +use syntax::ast::{crate, def_id, def_mod, def_ty}; use syntax::ast::{item, item_class, item_const, item_enum, item_fn}; use syntax::ast::{item_foreign_mod, item_impl, item_mac, item_mod}; use syntax::ast::{item_trait, item_ty, local_crate, method, node_id}; @@ -118,6 +119,21 @@ fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo { } } +// Stores the method info and definition ID of the associated trait method for +// each instantiation of each provided method. +struct ProvidedMethodInfo { + method_info: @MethodInfo, + trait_method_def_id: def_id +} + +// Stores information about provided methods (a.k.a. default methods) in +// implementations. +// +// This is a map from ID of each implementation to the method info and trait +// method ID of each of the default methods belonging to the trait that that +// implementation implements. +type ProvidedMethodsMap = HashMap>; + struct CoherenceInfo { // Contains implementations of methods that are inherent to a type. // Methods in these implementations don't need to be exported. @@ -128,14 +144,20 @@ struct CoherenceInfo { extension_methods: HashMap>, // A mapping from a supertrait to its subtraits. - supertrait_to_subtraits: HashMap> + supertrait_to_subtraits: HashMap>, + + // A mapping from an implementation ID to the method info and trait method + // ID of the provided (a.k.a. default) methods in the traits that that + // implementation implements. + provided_methods: ProvidedMethodsMap, } fn CoherenceInfo() -> CoherenceInfo { CoherenceInfo { inherent_methods: HashMap(), extension_methods: HashMap(), - supertrait_to_subtraits: HashMap() + supertrait_to_subtraits: HashMap(), + provided_methods: HashMap(), } } @@ -165,68 +187,6 @@ struct CoherenceChecker { } impl CoherenceChecker { - // Create a mapping containing a MethodInfo for every provided - // method in every trait. - fn build_provided_methods_map(crate: @crate) { - let sess = self.crate_context.tcx.sess; - - let pmm = self.crate_context.provided_methods_map; - - visit_crate(*crate, (), mk_simple_visitor(@{ - visit_item: |item| { - match item.node { - item_trait(_, _, trait_methods) => { - for trait_methods.each |trait_method| { - debug!("(building provided methods map) checking \ - trait `%s` with id %d", - sess.str_of(item.ident), item.id); - - match *trait_method { - required(_) => { /* fall through */} - provided(m) => { - // For every provided method in the - // trait, store a MethodInfo. - let mi = method_to_MethodInfo(m); - - match pmm.find(item.id) { - Some(mis) => { - // If the trait already has an - // entry in the - // provided_methods_map, we just - // need to add this method to - // that entry. - debug!("(building provided \ - methods map) adding \ - method `%s` to entry for \ - existing trait", - sess.str_of(mi.ident)); - let mut method_infos = mis; - method_infos.push(mi); - pmm.insert(item.id, method_infos); - } - None => { - // If the trait doesn't have an - // entry yet, create one. - debug!("(building provided \ - methods map) creating new \ - entry for method `%s`", - sess.str_of(mi.ident)); - pmm.insert(item.id, ~[mi]); - } - } - } - } - } - } - _ => { - // Nothing to do. - } - }; - }, - .. *default_simple_visitor() - })); - } - fn check_coherence(crate: @crate) { // Check implementations and traits. This populates the tables // containing the inherent methods and extension methods. It also @@ -307,6 +267,7 @@ impl CoherenceChecker { self.crate_context.tcx.sess.parse_sess.interner), self.crate_context.tcx.sess.str_of(item.ident)); + self.instantiate_default_methods(item.id, trait_did); let implementation = self.create_impl_from_item(item); self.add_trait_method(trait_did, implementation); } @@ -321,6 +282,7 @@ impl CoherenceChecker { // Nothing to do. } Some(base_type_def_id) => { + // XXX: Gather up default methods? let implementation = self.create_impl_from_item(item); self.add_inherent_method(base_type_def_id, implementation); @@ -330,6 +292,68 @@ impl CoherenceChecker { } } + // Creates default method IDs and performs type substitutions for an impl + // and trait pair. Then, for each provided method in the trait, inserts a + // `ProvidedMethodInfo` instance into the `provided_method_sources` map. + fn instantiate_default_methods(impl_id: ast::node_id, + trait_did: ast::def_id) { + for self.each_provided_trait_method(trait_did) |trait_method| { + // Synthesize an ID. + let tcx = self.crate_context.tcx; + let new_id = syntax::parse::next_node_id(tcx.sess.parse_sess); + let new_did = local_def(new_id); + + // XXX: Perform substitutions. + let new_polytype = ty::lookup_item_type(tcx, trait_method.def_id); + tcx.tcache.insert(new_did, new_polytype); + + // Pair the new synthesized ID up with the + // ID of the method. + let source = ProvidedMethodSource { + method_id: trait_method.def_id, + impl_id: local_def(impl_id) + }; + + self.crate_context.tcx.provided_method_sources.insert(new_did, + source); + + let provided_method_info = + @ProvidedMethodInfo { + method_info: @{ + did: new_did, + n_tps: trait_method.tps.len(), + ident: trait_method.ident, + self_type: trait_method.self_ty + }, + trait_method_def_id: trait_method.def_id + }; + + let pmm = self.crate_context.coherence_info.provided_methods; + match pmm.find(local_def(impl_id)) { + Some(mis) => { + // If the trait already has an entry in the + // provided_methods_map, we just need to add this + // method to that entry. + debug!("(checking implementation) adding method `%s` \ + to entry for existing trait", + self.crate_context.tcx.sess.str_of( + provided_method_info.method_info.ident)); + mis.push(provided_method_info); + } + None => { + // If the trait doesn't have an entry yet, create one. + debug!("(checking implementation) creating new entry \ + for method `%s`", + self.crate_context.tcx.sess.str_of( + provided_method_info.method_info.ident)); + let method_infos = @DVec(); + method_infos.push(provided_method_info); + pmm.insert(local_def(impl_id), method_infos); + } + } + } + } + fn register_inherited_trait(item: @item, supertraits: ~[@trait_ref]) { // XXX: This is wrong. We need to support substitutions; e.g. // trait Foo : Bar. @@ -354,8 +378,7 @@ impl CoherenceChecker { fn add_inherent_method(base_def_id: def_id, implementation: @Impl) { let implementation_list; match self.crate_context.coherence_info.inherent_methods - .find(base_def_id) { - + .find(base_def_id) { None => { implementation_list = @DVec(); self.crate_context.coherence_info.inherent_methods @@ -372,8 +395,7 @@ impl CoherenceChecker { fn add_trait_method(trait_id: def_id, implementation: @Impl) { let implementation_list; match self.crate_context.coherence_info.extension_methods - .find(trait_id) { - + .find(trait_id) { None => { implementation_list = @DVec(); self.crate_context.coherence_info.extension_methods @@ -413,6 +435,26 @@ impl CoherenceChecker { } } + fn each_provided_trait_method( + trait_did: ast::def_id, + f: &fn(x: &ty::method) -> bool) { + // Make a list of all the names of the provided methods. + // XXX: This is horrible. + let provided_method_idents = HashMap(); + let tcx = self.crate_context.tcx; + for ty::provided_trait_methods(tcx, trait_did).each |ident| { + provided_method_idents.insert(*ident, ()); + } + + for ty::trait_methods(tcx, trait_did).each |method| { + if provided_method_idents.contains_key(method.ident) { + if !f(method) { + break; + } + } + } + } + fn polytypes_unify(polytype_a: ty_param_bounds_and_ty, polytype_b: ty_param_bounds_and_ty) -> bool { @@ -449,7 +491,6 @@ impl CoherenceChecker { fn get_self_type_for_implementation(implementation: @Impl) -> ty_param_bounds_and_ty { - return self.crate_context.tcx.tcache.get(implementation.did); } @@ -552,33 +593,15 @@ impl CoherenceChecker { // Converts an implementation in the AST to an Impl structure. fn create_impl_from_item(item: @item) -> @Impl { - - fn add_provided_methods(inherent_methods: ~[@MethodInfo], - all_provided_methods: ~[@MethodInfo], - sess: driver::session::session) - -> ~[@MethodInfo] { - - let mut methods = inherent_methods; - - // If there's no inherent method with the same name as a - // provided method, add that provided method to `methods`. + fn add_provided_methods(all_methods: &mut ~[@MethodInfo], + all_provided_methods: ~[@ProvidedMethodInfo], + sess: driver::session::session) { for all_provided_methods.each |provided_method| { - let mut method_inherent_to_impl = false; - for inherent_methods.each |inherent_method| { - if provided_method.ident == inherent_method.ident { - method_inherent_to_impl = true; - } - } - - if !method_inherent_to_impl { - debug!( - "(creating impl) adding provided method `%s` to impl", - sess.str_of(provided_method.ident)); - methods.push(*provided_method); - } + debug!( + "(creating impl) adding provided method `%s` to impl", + sess.str_of(provided_method.method_info.ident)); + vec::push(all_methods, provided_method.method_info); } - - return methods; } match item.node { @@ -598,24 +621,22 @@ impl CoherenceChecker { let trait_did = self.trait_ref_to_trait_def_id(*trait_ref); - match self.crate_context.provided_methods_map - .find(trait_did.node) { + match self.crate_context + .coherence_info + .provided_methods + .find(local_def(item.id)) { None => { debug!("(creating impl) trait with node_id `%d` \ has no provided methods", trait_did.node); /* fall through */ } - Some(all_provided) - => { + Some(all_provided) => { debug!("(creating impl) trait with node_id `%d` \ has provided methods", trait_did.node); - // Selectively add only those provided - // methods that aren't inherent to the - // trait. - - // XXX: could probably be doing this with filter. - methods = add_provided_methods( - methods, all_provided, + // Add all provided methods. + add_provided_methods( + &mut methods, + all_provided.get(), self.crate_context.tcx.sess); } } @@ -758,6 +779,41 @@ impl CoherenceChecker { } } + fn add_default_methods_for_external_trait(trait_def_id: ast::def_id) { + let tcx = self.crate_context.tcx; + let pmm = self.crate_context.coherence_info.provided_methods; + + if pmm.contains_key(trait_def_id) { return; } + + debug!("(adding default methods for trait) processing trait"); + + for csearch::get_provided_trait_methods(tcx, + trait_def_id).each |info| { + debug!("(adding default methods for trait) found default method"); + + // Create a new def ID for this provided method. + let parse_sess = &self.crate_context.tcx.sess.parse_sess; + let new_did = local_def(syntax::parse::next_node_id(*parse_sess)); + + let provided_method_info = + @ProvidedMethodInfo { + method_info: @{ + did: new_did, + n_tps: info.ty.tps.len(), + ident: info.ty.ident, + self_type: info.ty.self_ty + }, + trait_method_def_id: info.def_id + }; + + let method_infos = @DVec(); + method_infos.push(provided_method_info); + pmm.insert(trait_def_id, method_infos); + } + } + + // Adds implementations and traits from external crates to the coherence + // info. fn add_external_crates() { let impls_seen = HashMap(); @@ -768,20 +824,28 @@ impl CoherenceChecker { { crate: crate_number, node: 0 }); for each_path(crate_store, crate_number) |path_entry| { - let module_def_id; match path_entry.def_like { dl_def(def_mod(def_id)) => { - module_def_id = def_id; + self.add_impls_for_module(impls_seen, + crate_store, + def_id); + } + dl_def(def_ty(def_id)) => { + let tcx = self.crate_context.tcx; + let polytype = csearch::get_type(tcx, def_id); + match ty::get(polytype.ty).sty { + ty::ty_trait(*) => { + self.add_default_methods_for_external_trait( + def_id); + } + _ => {} + } } dl_def(_) | dl_impl(_) | dl_field => { // Skip this. loop; } } - - self.add_impls_for_module(impls_seen, - crate_store, - module_def_id); } } } @@ -789,7 +853,6 @@ impl CoherenceChecker { fn check_coherence(crate_context: @crate_ctxt, crate: @crate) { let coherence_checker = @CoherenceChecker(crate_context); - (*coherence_checker).build_provided_methods_map(crate); (*coherence_checker).check_coherence(crate); } diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index a38e69effdff..9e51225f172f 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -212,9 +212,15 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) { match tcx.items.get(id) { ast_map::node_item(@{node: ast::item_trait(params, _, ms), _}, _) => { store_methods::(ccx, id, ms, |m| { + let def_id; + match *m { + ast::required(ty_method) => def_id = local_def(ty_method.id), + ast::provided(method) => def_id = local_def(method.id) + } + let trait_bounds = ty_param_bounds(ccx, params); let ty_m = trait_method_to_ty_method(*m); - let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd); + let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id); if ty_m.self_ty.node == ast::sty_static { make_static_method_ty(ccx, ty_m, region_paramd, method_ty, trait_ty, trait_bounds); @@ -373,7 +379,7 @@ fn check_methods_against_trait(ccx: @crate_ctxt, let provided_methods = ty::provided_trait_methods(tcx, did); match vec::find(provided_methods, |provided_method| - provided_method.ident == trait_m.ident) { + *provided_method == trait_m.ident) { Some(_) => { // If there's a provided method with the name we // want, then we're fine; nothing else to do. @@ -546,19 +552,22 @@ fn ty_of_method(ccx: @crate_ctxt, m.purity, @~[], m.decl, None, m.span), self_ty: m.self_ty.node, - vis: m.vis} + vis: m.vis, + def_id: local_def(m.id)} } fn ty_of_ty_method(self: @crate_ctxt, m: ast::ty_method, - rp: Option) -> ty::method { + rp: Option, + id: ast::def_id) -> ty::method { {ident: m.ident, tps: ty_param_bounds(self, m.tps), fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare, m.purity, @~[], m.decl, None, m.span), // assume public, because this is only invoked on trait methods self_ty: m.self_ty.node, - vis: ast::public} + vis: ast::public, + def_id: id} } /* diff --git a/src/test/run-pass/default-method-simple.rs b/src/test/run-pass/default-method-simple.rs new file mode 100644 index 000000000000..6a05d9589130 --- /dev/null +++ b/src/test/run-pass/default-method-simple.rs @@ -0,0 +1,23 @@ +trait Foo { + fn f() { + io::println("Hello!"); + self.g(); + } + fn g(); +} + +struct A { + x: int +} + +impl A : Foo { + fn g() { + io::println("Goodbye!"); + } +} + +fn main() { + let a = A { x: 1 }; + a.f(); +} + From 4f9e7babeb3fce422072f51959470ecec4dead53 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 14:17:16 -0700 Subject: [PATCH 205/292] Un-xfail test for #3521; it works now Closes #3521 --- src/test/{run-pass => compile-fail}/issue-3521.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename src/test/{run-pass => compile-fail}/issue-3521.rs (50%) diff --git a/src/test/run-pass/issue-3521.rs b/src/test/compile-fail/issue-3521.rs similarity index 50% rename from src/test/run-pass/issue-3521.rs rename to src/test/compile-fail/issue-3521.rs index d8693fe18d35..9ad483367fe9 100644 --- a/src/test/run-pass/issue-3521.rs +++ b/src/test/compile-fail/issue-3521.rs @@ -1,9 +1,8 @@ -// xfail-test fn main() { let foo = 100; enum Stuff { - Bar = foo + Bar = foo //~ ERROR attempt to use a non-constant value in a constant } log(error, Bar); From c5b82a65e96cfe77e4983e78a34a7d5aa91329b4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 14:33:32 -0700 Subject: [PATCH 206/292] Add test cases for #3668 Previous commits fix the issue. Closes #3668 --- src/test/compile-fail/issue-3668-2.rs | 5 +++++ src/test/{run-pass => compile-fail}/issue-3668.rs | 3 +-- src/test/run-pass/issue-3688-2.rs | 6 ------ 3 files changed, 6 insertions(+), 8 deletions(-) create mode 100644 src/test/compile-fail/issue-3668-2.rs rename src/test/{run-pass => compile-fail}/issue-3668.rs (63%) delete mode 100644 src/test/run-pass/issue-3688-2.rs diff --git a/src/test/compile-fail/issue-3668-2.rs b/src/test/compile-fail/issue-3668-2.rs new file mode 100644 index 000000000000..89c9e2b2e91e --- /dev/null +++ b/src/test/compile-fail/issue-3668-2.rs @@ -0,0 +1,5 @@ +fn f(x:int) { + const child: int = x + 1; //~ ERROR attempt to use a non-constant value in a constant +} + +fn main() {} diff --git a/src/test/run-pass/issue-3668.rs b/src/test/compile-fail/issue-3668.rs similarity index 63% rename from src/test/run-pass/issue-3668.rs rename to src/test/compile-fail/issue-3668.rs index 8b3005a3589d..6cbd64c6aa9b 100644 --- a/src/test/run-pass/issue-3668.rs +++ b/src/test/compile-fail/issue-3668.rs @@ -1,4 +1,3 @@ -// xfail-test struct P { child: Option<@mut P> } trait PTrait { fn getChildOption() -> Option<@P>; @@ -6,7 +5,7 @@ trait PTrait { impl P: PTrait { fn getChildOption() -> Option<@P> { - const childVal: @P = self.child.get(); + const childVal: @P = self.child.get(); //~ ERROR attempt to use a non-constant value in a constant fail; } } diff --git a/src/test/run-pass/issue-3688-2.rs b/src/test/run-pass/issue-3688-2.rs deleted file mode 100644 index 8a5b0e26829c..000000000000 --- a/src/test/run-pass/issue-3688-2.rs +++ /dev/null @@ -1,6 +0,0 @@ -// xfail-test -fn f(x:int) { - const child: int = x + 1; -} - -fn main() {} From 91ae5412d8141ea958924408bf3c1def5edca806 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 15 Oct 2012 14:56:42 -0700 Subject: [PATCH 207/292] rustc: Merge module and type namespaces. r=brson --- src/fuzzer/fuzzer.rs | 18 +- src/libcore/cmath.rs | 4 +- src/libcore/f32.rs | 2 +- src/libcore/f64.rs | 4 +- src/libcore/libc.rs | 6 +- src/libsyntax/ast.rs | 50 +- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/codemap.rs | 36 +- src/libsyntax/diagnostic.rs | 19 +- src/libsyntax/ext/auto_serialize.rs | 8 +- src/libsyntax/ext/base.rs | 6 +- src/libsyntax/ext/pipes.rs | 4 +- src/libsyntax/ext/pipes/ast_builder.rs | 60 +-- src/libsyntax/ext/pipes/check.rs | 4 +- src/libsyntax/ext/pipes/parse_proto.rs | 2 +- src/libsyntax/ext/pipes/pipec.rs | 8 +- src/libsyntax/ext/pipes/proto.rs | 10 +- src/libsyntax/ext/qquote.rs | 22 +- src/libsyntax/ext/simplext.rs | 4 +- src/libsyntax/ext/trace_macros.rs | 6 +- src/libsyntax/ext/tt/macro_parser.rs | 12 +- src/libsyntax/ext/tt/macro_rules.rs | 6 +- src/libsyntax/ext/tt/transcribe.rs | 9 +- src/libsyntax/fold.rs | 4 +- src/libsyntax/parse.rs | 24 +- src/libsyntax/parse/attr.rs | 2 +- src/libsyntax/parse/common.rs | 94 ++-- src/libsyntax/parse/eval.rs | 2 +- src/libsyntax/parse/lexer.rs | 26 +- src/libsyntax/parse/obsolete.rs | 6 +- src/libsyntax/parse/parser.rs | 70 +-- src/libsyntax/parse/prec.rs | 4 +- src/libsyntax/parse/token.rs | 30 +- src/libsyntax/print/pprust.rs | 14 +- src/libsyntax/util/interner.rs | 10 +- src/libsyntax/visit.rs | 12 +- src/rustc/back/link.rs | 26 +- src/rustc/back/rpath.rs | 4 +- src/rustc/driver/driver.rs | 29 +- src/rustc/driver/rustc.rs | 2 +- src/rustc/driver/session.rs | 16 +- src/rustc/front/core_inject.rs | 6 +- src/rustc/front/intrinsic_inject.rs | 4 +- src/rustc/front/test.rs | 14 +- src/rustc/metadata/creader.rs | 8 +- src/rustc/metadata/csearch.rs | 20 +- src/rustc/metadata/cstore.rs | 40 +- src/rustc/metadata/encoder.rs | 8 +- src/rustc/metadata/filesearch.rs | 12 +- src/rustc/metadata/loader.rs | 6 +- src/rustc/metadata/tydecode.rs | 2 +- src/rustc/metadata/tyencode.rs | 2 +- src/rustc/middle/astencode.rs | 8 +- src/rustc/middle/borrowck.rs | 7 +- src/rustc/middle/borrowck/gather_loans.rs | 4 +- src/rustc/middle/borrowck/loan.rs | 6 +- src/rustc/middle/borrowck/preserve.rs | 6 +- src/rustc/middle/capture.rs | 1 - src/rustc/middle/check_alt.rs | 1 - src/rustc/middle/check_const.rs | 12 +- src/rustc/middle/check_loop.rs | 1 - src/rustc/middle/kind.rs | 7 +- src/rustc/middle/lang_items.rs | 12 +- src/rustc/middle/lint.rs | 6 +- src/rustc/middle/liveness.rs | 1 - src/rustc/middle/mem_categorization.rs | 4 +- src/rustc/middle/region.rs | 16 +- src/rustc/middle/resolve.rs | 458 ++++++++---------- src/rustc/middle/trans/alt.rs | 1 - src/rustc/middle/trans/base.rs | 6 +- src/rustc/middle/trans/build.rs | 1 - src/rustc/middle/trans/common.rs | 8 +- src/rustc/middle/trans/debuginfo.rs | 8 +- src/rustc/middle/trans/foreign.rs | 2 +- src/rustc/middle/trans/reachable.rs | 2 +- src/rustc/middle/trans/reflect.rs | 1 - src/rustc/middle/trans/tvec.rs | 1 - src/rustc/middle/trans/type_use.rs | 1 - src/rustc/middle/ty.rs | 144 +++--- src/rustc/middle/typeck.rs | 1 - src/rustc/middle/typeck/astconv.rs | 6 +- src/rustc/middle/typeck/check.rs | 34 +- src/rustc/middle/typeck/check/alt.rs | 4 +- src/rustc/middle/typeck/check/method.rs | 4 +- src/rustc/middle/typeck/check/regionck.rs | 12 +- src/rustc/middle/typeck/check/regionmanip.rs | 8 +- src/rustc/middle/typeck/coherence.rs | 6 +- src/rustc/middle/typeck/collect.rs | 4 +- src/rustc/middle/typeck/infer.rs | 15 +- src/rustc/middle/typeck/infer/assignment.rs | 4 +- src/rustc/middle/typeck/infer/combine.rs | 18 +- src/rustc/middle/typeck/infer/glb.rs | 6 +- src/rustc/middle/typeck/infer/integral.rs | 2 +- src/rustc/middle/typeck/infer/lattice.rs | 2 +- src/rustc/middle/typeck/infer/lub.rs | 6 +- .../typeck/infer/region_var_bindings.rs | 58 +-- src/rustc/middle/typeck/infer/resolve.rs | 10 +- src/rustc/middle/typeck/infer/sub.rs | 6 +- src/rustc/middle/typeck/infer/to_str.rs | 16 +- src/rustc/middle/typeck/infer/unify.rs | 4 +- src/rustc/middle/typeck/rscope.rs | 36 +- src/rustc/util/common.rs | 1 - src/rustc/util/ppaux.rs | 13 +- src/rustdoc/astsrv.rs | 14 +- src/rustdoc/parse.rs | 6 +- src/test/run-pass/issue-2930.rs | 4 +- src/test/run-pass/pipe-select.rs | 4 +- 107 files changed, 877 insertions(+), 951 deletions(-) diff --git a/src/fuzzer/fuzzer.rs b/src/fuzzer/fuzzer.rs index 3e31287e3cd1..018972d4c3e0 100644 --- a/src/fuzzer/fuzzer.rs +++ b/src/fuzzer/fuzzer.rs @@ -104,7 +104,7 @@ pure fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool { } } -fn safe_to_steal_ty(t: @ast::ty, tm: test_mode) -> bool { +fn safe_to_steal_ty(t: @ast::Ty, tm: test_mode) -> bool { // Restrictions happen to be the same. safe_to_replace_ty(t.node, tm) } @@ -119,16 +119,16 @@ fn stash_expr_if(c: fn@(@ast::expr, test_mode)->bool, } else {/* now my indices are wrong :( */ } } -fn stash_ty_if(c: fn@(@ast::ty, test_mode)->bool, - es: @mut ~[ast::ty], - e: @ast::ty, +fn stash_ty_if(c: fn@(@ast::Ty, test_mode)->bool, + es: @mut ~[ast::Ty], + e: @ast::Ty, tm: test_mode) { if c(e, tm) { es.push(*e); } else {/* now my indices are wrong :( */ } } -type stolen_stuff = {exprs: ~[ast::expr], tys: ~[ast::ty]}; +type stolen_stuff = {exprs: ~[ast::expr], tys: ~[ast::Ty]}; fn steal(crate: ast::crate, tm: test_mode) -> stolen_stuff { let exprs = @mut ~[]; @@ -195,7 +195,7 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint, // Replace the |i|th ty (in fold order) of |crate| with |newty|. -fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::ty, +fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::Ty, tm: test_mode) -> ast::crate { let j: @mut uint = @mut 0u; fn fold_ty_rep(j_: @mut uint, i_: uint, newty_: ast::ty_, @@ -225,7 +225,7 @@ fn as_str(f: fn@(+x: io::Writer)) -> ~str { io::with_str_writer(f) } -fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap, +fn check_variants_of_ast(crate: ast::crate, codemap: codemap::CodeMap, filename: &Path, cx: context) { let stolen = steal(crate, cx.mode); let extra_exprs = vec::filter(common_exprs(), @@ -239,7 +239,7 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap, fn check_variants_T( crate: ast::crate, - codemap: codemap::codemap, + codemap: codemap::CodeMap, filename: &Path, thing_label: ~str, things: ~[T], @@ -444,7 +444,7 @@ fn parse_and_print(code: @~str) -> ~str { fn has_raw_pointers(c: ast::crate) -> bool { let has_rp = @mut false; - fn visit_ty(flag: @mut bool, t: @ast::ty) { + fn visit_ty(flag: @mut bool, t: @ast::Ty) { match t.node { ast::ty_ptr(_) => { *flag = true; } _ => { } diff --git a/src/libcore/cmath.rs b/src/libcore/cmath.rs index b0aeb78afaa8..46ac90413a64 100644 --- a/src/libcore/cmath.rs +++ b/src/libcore/cmath.rs @@ -12,7 +12,7 @@ use libc::c_double; #[link_name = "m"] #[abi = "cdecl"] -pub extern mod c_double { +pub extern mod c_double_utils { // Alpabetically sorted by link_name @@ -87,7 +87,7 @@ pub extern mod c_double { #[link_name = "m"] #[abi = "cdecl"] -pub extern mod c_float { +pub extern mod c_float_utils { // Alpabetically sorted by link_name diff --git a/src/libcore/f32.rs b/src/libcore/f32.rs index ec0e66734fa3..ed6908d110d6 100644 --- a/src/libcore/f32.rs +++ b/src/libcore/f32.rs @@ -4,7 +4,7 @@ //! Operations and constants for `f32` -pub use cmath::c_float::*; +pub use cmath::c_float_utils::*; pub use cmath::c_float_targ_consts::*; // These are not defined inside consts:: for consistency with diff --git a/src/libcore/f64.rs b/src/libcore/f64.rs index 731d369649b1..2d13dc86e2fa 100644 --- a/src/libcore/f64.rs +++ b/src/libcore/f64.rs @@ -4,7 +4,7 @@ //! Operations and constants for `f64` -pub use cmath::c_double::*; +pub use cmath::c_double_utils::*; pub use cmath::c_double_targ_consts::*; // FIXME (#1433): obtain these in a different way @@ -59,7 +59,7 @@ pub pure fn ge(x: f64, y: f64) -> bool { return x >= y; } pub pure fn gt(x: f64, y: f64) -> bool { return x > y; } pub pure fn sqrt(x: f64) -> f64 { - cmath::c_double::sqrt(x as libc::c_double) as f64 + cmath::c_double_utils::sqrt(x as libc::c_double) as f64 } /// Returns true if `x` is a positive number, including +0.0f640 and +Infinity diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index dd8f76c89d5f..7ed43f619e13 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -87,7 +87,7 @@ pub use funcs::extra::*; pub use size_t; pub use c_float, c_double, c_void, FILE, fpos_t; -pub use DIR, dirent; +pub use DIR, dirent_t; pub use c_char, c_schar, c_uchar; pub use c_short, c_ushort, c_int, c_uint, c_long, c_ulong; pub use size_t, ptrdiff_t, clock_t, time_t; @@ -147,7 +147,7 @@ mod types { } pub mod posix88 { pub enum DIR {} - pub enum dirent {} + pub enum dirent_t {} } pub mod posix01 {} pub mod posix08 {} @@ -1019,7 +1019,7 @@ pub mod funcs { pub extern mod dirent { fn opendir(dirname: *c_char) -> *DIR; fn closedir(dirp: *DIR) -> c_int; - fn readdir(dirp: *DIR) -> *dirent; + fn readdir(dirp: *DIR) -> *dirent_t; fn rewinddir(dirp: *DIR); fn seekdir(dirp: *DIR, loc: c_long); fn telldir(dirp: *DIR) -> c_long; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index cf7b758216b9..e3da15d181b7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -129,7 +129,7 @@ type path = {span: span, global: bool, idents: ~[ident], rp: Option<@region>, - types: ~[@ty]}; + types: ~[@Ty]}; type crate_num = int; @@ -156,7 +156,7 @@ enum ty_param_bound { bound_send, bound_const, bound_owned, - bound_trait(@ty), + bound_trait(@Ty), } #[auto_serialize] @@ -702,7 +702,7 @@ type initializer = {op: init_op, expr: @expr}; // a refinement on pat. #[auto_serialize] #[auto_deserialize] -type local_ = {is_mutbl: bool, ty: @ty, pat: @pat, +type local_ = {is_mutbl: bool, ty: @Ty, pat: @pat, init: Option, id: node_id}; type local = spanned; @@ -764,7 +764,7 @@ enum expr_ { expr_binary(binop, @expr, @expr), expr_unary(unop, @expr), expr_lit(@lit), - expr_cast(@expr, @ty), + expr_cast(@expr, @Ty), expr_if(@expr, blk, Option<@expr>), expr_while(@expr, blk), /* Conditionless loop (can be exited with break, cont, ret, or fail) @@ -788,7 +788,7 @@ enum expr_ { expr_assign(@expr, @expr), expr_swap(@expr, @expr), expr_assign_op(binop, @expr, @expr), - expr_field(@expr, ident, ~[@ty]), + expr_field(@expr, ident, ~[@Ty]), expr_index(@expr, @expr), expr_path(@path), expr_addr_of(mutability, @expr), @@ -843,10 +843,10 @@ type capture_clause = @~[capture_item]; #[auto_deserialize] #[doc="For macro invocations; parsing is delegated to the macro"] enum token_tree { - tt_tok(span, token::token), + tt_tok(span, token::Token), tt_delim(~[token_tree]), // These only make sense for right-hand-sides of MBE macros - tt_seq(span, ~[token_tree], Option, bool), + tt_seq(span, ~[token_tree], Option, bool), tt_nonterminal(span, ident) } @@ -908,10 +908,10 @@ type matcher = spanned; #[auto_deserialize] enum matcher_ { // match one token - match_tok(token::token), + match_tok(token::Token), // match repetitions of a sequence: body, separator, zero ok?, // lo, hi position-in-match-array used: - match_seq(~[matcher], Option, bool, uint, uint), + match_seq(~[matcher], Option, bool, uint, uint), // parse a Rust NT: name to bind, name of NT, position in match array: match_nonterminal(ident, ident, uint) } @@ -984,7 +984,7 @@ impl ast::lit_: cmp::Eq { // type structure in middle/ty.rs as well. #[auto_serialize] #[auto_deserialize] -type mt = {ty: @ty, mutbl: mutability}; +type mt = {ty: @Ty, mutbl: mutability}; #[auto_serialize] #[auto_deserialize] @@ -1087,7 +1087,7 @@ impl float_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] -type ty = {id: node_id, node: ty_, span: span}; +type Ty = {id: node_id, node: ty_, span: span}; // Not represented directly in the AST, referred to by name through a ty_path. #[auto_serialize] @@ -1163,9 +1163,9 @@ enum ty_ { ty_rptr(@region, mt), ty_rec(~[ty_field]), ty_fn(proto, purity, @~[ty_param_bound], fn_decl), - ty_tup(~[@ty]), + ty_tup(~[@Ty]), ty_path(@path, node_id), - ty_fixed_length(@ty, Option), + ty_fixed_length(@Ty, Option), ty_mac(mac), // ty_infer means the type should be inferred instead of it having been // specified. This should only appear at the "top level" of a type and not @@ -1175,16 +1175,16 @@ enum ty_ { // Equality and byte-iter (hashing) can be quite approximate for AST types. // since we only care about this for normalizing them to "real" types. -impl ty : cmp::Eq { - pure fn eq(other: &ty) -> bool { +impl Ty : cmp::Eq { + pure fn eq(other: &Ty) -> bool { ptr::addr_of(&self) == ptr::addr_of(&(*other)) } - pure fn ne(other: &ty) -> bool { + pure fn ne(other: &Ty) -> bool { ptr::addr_of(&self) != ptr::addr_of(&(*other)) } } -impl ty : to_bytes::IterBytes { +impl Ty : to_bytes::IterBytes { pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.span.lo, &self.span.hi, lsb0, f); } @@ -1193,13 +1193,13 @@ impl ty : to_bytes::IterBytes { #[auto_serialize] #[auto_deserialize] -type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; +type arg = {mode: mode, ty: @Ty, ident: ident, id: node_id}; #[auto_serialize] #[auto_deserialize] type fn_decl = {inputs: ~[arg], - output: @ty, + output: @Ty, cf: ret_style}; #[auto_serialize] @@ -1362,7 +1362,7 @@ type foreign_mod = #[auto_serialize] #[auto_deserialize] -type variant_arg = {ty: @ty, id: node_id}; +type variant_arg = {ty: @Ty, id: node_id}; #[auto_serialize] #[auto_deserialize] @@ -1495,7 +1495,7 @@ impl visibility : cmp::Eq { type struct_field_ = { kind: struct_field_kind, id: node_id, - ty: @ty + ty: @Ty }; type struct_field = spanned; @@ -1531,17 +1531,17 @@ type item = {ident: ident, attrs: ~[attribute], #[auto_serialize] #[auto_deserialize] enum item_ { - item_const(@ty, @expr), + item_const(@Ty, @expr), item_fn(fn_decl, purity, ~[ty_param], blk), item_mod(_mod), item_foreign_mod(foreign_mod), - item_ty(@ty, ~[ty_param]), + item_ty(@Ty, ~[ty_param]), item_enum(enum_def, ~[ty_param]), item_class(@struct_def, ~[ty_param]), item_trait(~[ty_param], ~[@trait_ref], ~[trait_method]), item_impl(~[ty_param], Option<@trait_ref>, /* (optional) trait this impl implements */ - @ty, /* self */ + @Ty, /* self */ ~[@method]), item_mac(mac), } @@ -1601,7 +1601,7 @@ type foreign_item = #[auto_deserialize] enum foreign_item_ { foreign_item_fn(fn_decl, purity, ~[ty_param]), - foreign_item_const(@ty) + foreign_item_const(@Ty) } // The data we save and restore about an inlined item or method. This is not diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 4c18b6b8ecac..6fd84c3317f7 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -471,7 +471,7 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { visit_expr_post: fn@(_e: @expr) { }, - visit_ty: fn@(t: @ty) { + visit_ty: fn@(t: @Ty) { match t.node { ty_path(_, id) => vfn(id), _ => { /* fall through */ } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index e07985119ec4..0cb8b425c942 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -7,7 +7,7 @@ export file_substr; export fss_none; export fss_internal; export fss_external; -export codemap; +export CodeMap; export expn_info; export expn_info_; export expanded_from; @@ -55,11 +55,11 @@ type filemap = @{name: filename, substr: file_substr, src: @~str, start_pos: file_pos, mut lines: ~[file_pos]}; -type codemap = @{files: DVec}; +type CodeMap = @{files: DVec}; type loc = {file: filemap, line: uint, col: uint}; -fn new_codemap() -> codemap { @{files: DVec()} } +fn new_codemap() -> CodeMap { @{files: DVec()} } fn new_filemap_w_substr(+filename: filename, +substr: file_substr, src: @~str, @@ -77,7 +77,7 @@ fn new_filemap(+filename: filename, src: @~str, start_pos_ch, start_pos_byte); } -fn mk_substr_filename(cm: codemap, sp: span) -> ~str +fn mk_substr_filename(cm: CodeMap, sp: span) -> ~str { let pos = lookup_char_pos(cm, sp.lo); return fmt!("<%s:%u:%u>", pos.file.name, pos.line, pos.col); @@ -89,7 +89,7 @@ fn next_line(file: filemap, chpos: uint, byte_pos: uint) { type lookup_fn = pure fn(file_pos) -> uint; -fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn) +fn lookup_line(map: CodeMap, pos: uint, lookup: lookup_fn) -> {fm: filemap, line: uint} { let len = map.files.len(); @@ -112,22 +112,22 @@ fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn) return {fm: f, line: a}; } -fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc { +fn lookup_pos(map: CodeMap, pos: uint, lookup: lookup_fn) -> loc { let {fm: f, line: a} = lookup_line(map, pos, lookup); return {file: f, line: a + 1u, col: pos - lookup(f.lines[a])}; } -fn lookup_char_pos(map: codemap, pos: uint) -> loc { +fn lookup_char_pos(map: CodeMap, pos: uint) -> loc { pure fn lookup(pos: file_pos) -> uint { return pos.ch; } return lookup_pos(map, pos, lookup); } -fn lookup_byte_pos(map: codemap, pos: uint) -> loc { +fn lookup_byte_pos(map: CodeMap, pos: uint) -> loc { pure fn lookup(pos: file_pos) -> uint { return pos.byte; } return lookup_pos(map, pos, lookup); } -fn lookup_char_pos_adj(map: codemap, pos: uint) +fn lookup_char_pos_adj(map: CodeMap, pos: uint) -> {filename: ~str, line: uint, col: uint, file: Option} { let loc = lookup_char_pos(map, pos); @@ -150,7 +150,7 @@ fn lookup_char_pos_adj(map: codemap, pos: uint) } } -fn adjust_span(map: codemap, sp: span) -> span { +fn adjust_span(map: CodeMap, sp: span) -> span { pure fn lookup(pos: file_pos) -> uint { return pos.ch; } let line = lookup_line(map, sp.lo, lookup); match (line.fm.substr) { @@ -178,14 +178,14 @@ impl span : cmp::Eq { pure fn ne(other: &span) -> bool { !self.eq(other) } } -fn span_to_str_no_adj(sp: span, cm: codemap) -> ~str { +fn span_to_str_no_adj(sp: span, cm: CodeMap) -> ~str { let lo = lookup_char_pos(cm, sp.lo); let hi = lookup_char_pos(cm, sp.hi); return fmt!("%s:%u:%u: %u:%u", lo.file.name, lo.line, lo.col, hi.line, hi.col) } -fn span_to_str(sp: span, cm: codemap) -> ~str { +fn span_to_str(sp: span, cm: CodeMap) -> ~str { let lo = lookup_char_pos_adj(cm, sp.lo); let hi = lookup_char_pos_adj(cm, sp.hi); return fmt!("%s:%u:%u: %u:%u", lo.filename, @@ -194,12 +194,12 @@ fn span_to_str(sp: span, cm: codemap) -> ~str { type file_lines = {file: filemap, lines: ~[uint]}; -fn span_to_filename(sp: span, cm: codemap::codemap) -> filename { +fn span_to_filename(sp: span, cm: codemap::CodeMap) -> filename { let lo = lookup_char_pos(cm, sp.lo); return /* FIXME (#2543) */ copy lo.file.name; } -fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines { +fn span_to_lines(sp: span, cm: codemap::CodeMap) -> @file_lines { let lo = lookup_char_pos(cm, sp.lo); let hi = lookup_char_pos(cm, sp.hi); let mut lines = ~[]; @@ -218,7 +218,7 @@ fn get_line(fm: filemap, line: int) -> ~str unsafe { str::slice(*fm.src, begin, end) } -fn lookup_byte_offset(cm: codemap::codemap, chpos: uint) +fn lookup_byte_offset(cm: codemap::CodeMap, chpos: uint) -> {fm: filemap, pos: uint} { pure fn lookup(pos: file_pos) -> uint { return pos.ch; } let {fm, line} = lookup_line(cm, chpos, lookup); @@ -228,20 +228,20 @@ fn lookup_byte_offset(cm: codemap::codemap, chpos: uint) {fm: fm, pos: line_offset + col_offset} } -fn span_to_snippet(sp: span, cm: codemap::codemap) -> ~str { +fn span_to_snippet(sp: span, cm: codemap::CodeMap) -> ~str { let begin = lookup_byte_offset(cm, sp.lo); let end = lookup_byte_offset(cm, sp.hi); assert begin.fm.start_pos == end.fm.start_pos; return str::slice(*begin.fm.src, begin.pos, end.pos); } -fn get_snippet(cm: codemap::codemap, fidx: uint, lo: uint, hi: uint) -> ~str +fn get_snippet(cm: codemap::CodeMap, fidx: uint, lo: uint, hi: uint) -> ~str { let fm = cm.files[fidx]; return str::slice(*fm.src, lo, hi) } -fn get_filemap(cm: codemap, filename: ~str) -> filemap { +fn get_filemap(cm: CodeMap, filename: ~str) -> filemap { for cm.files.each |fm| { if fm.name == filename { return *fm; } } //XXjdm the following triggers a mismatched type bug // (or expected function, found _|_) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 2addb3d9e12a..855b0ca3ef56 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -9,7 +9,7 @@ export codemap_span_handler, codemap_handler; export ice_msg; export expect; -type emitter = fn@(cmsp: Option<(codemap::codemap, span)>, +type emitter = fn@(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level); @@ -33,7 +33,7 @@ trait handler { fn note(msg: &str); fn bug(msg: &str) -> !; fn unimpl(msg: &str) -> !; - fn emit(cmsp: Option<(codemap::codemap, span)>, msg: &str, lvl: level); + fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level); } type handler_t = @{ @@ -43,7 +43,7 @@ type handler_t = @{ type codemap_t = @{ handler: handler, - cm: codemap::codemap + cm: codemap::CodeMap }; impl codemap_t: span_handler { @@ -107,7 +107,7 @@ impl handler_t: handler { self.fatal(ice_msg(msg)); } fn unimpl(msg: &str) -> ! { self.bug(~"unimplemented " + msg); } - fn emit(cmsp: Option<(codemap::codemap, span)>, msg: &str, lvl: level) { + fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level) { self.emit(cmsp, msg, lvl); } } @@ -116,7 +116,7 @@ fn ice_msg(msg: &str) -> ~str { fmt!("internal compiler error: %s", msg) } -fn mk_span_handler(handler: handler, cm: codemap::codemap) -> span_handler { +fn mk_span_handler(handler: handler, cm: codemap::CodeMap) -> span_handler { @{ handler: handler, cm: cm } as span_handler } @@ -125,7 +125,7 @@ fn mk_handler(emitter: Option) -> handler { let emit = match emitter { Some(e) => e, None => { - let f = fn@(cmsp: Option<(codemap::codemap, span)>, + let f = fn@(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, t: level) { emit(cmsp, msg, t); }; @@ -189,8 +189,7 @@ fn print_diagnostic(topic: ~str, lvl: level, msg: &str) { io::stderr().write_str(fmt!(" %s\n", msg)); } -fn emit(cmsp: Option<(codemap::codemap, span)>, - msg: &str, lvl: level) { +fn emit(cmsp: Option<(codemap::CodeMap, span)>, msg: &str, lvl: level) { match cmsp { Some((cm, sp)) => { let sp = codemap::adjust_span(cm,sp); @@ -206,7 +205,7 @@ fn emit(cmsp: Option<(codemap::codemap, span)>, } } -fn highlight_lines(cm: codemap::codemap, sp: span, +fn highlight_lines(cm: codemap::CodeMap, sp: span, lines: @codemap::file_lines) { let fm = lines.file; @@ -261,7 +260,7 @@ fn highlight_lines(cm: codemap::codemap, sp: span, } } -fn print_macro_backtrace(cm: codemap::codemap, sp: span) { +fn print_macro_backtrace(cm: codemap::CodeMap, sp: span) { do option::iter(&sp.expn_info) |ei| { let ss = option::map_default(&ei.callie.span, @~"", |span| @codemap::span_to_str(*span, cm)); diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 452becbe559a..7e5e68ffff90 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -250,12 +250,12 @@ priv impl ext_ctxt { } fn path_tps(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::path { + tps: ~[@ast::Ty]) -> @ast::path { @{span: span, global: false, idents: strs, rp: None, types: tps} } fn ty_path(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::ty { + tps: ~[@ast::Ty]) -> @ast::Ty { @{id: self.next_id(), node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), span: span} @@ -360,7 +360,7 @@ fn mk_impl( ty_param: ast::ty_param, path: @ast::path, tps: ~[ast::ty_param], - f: fn(@ast::ty) -> @ast::method + f: fn(@ast::Ty) -> @ast::method ) -> @ast::item { // All the type parameters need to bound to the trait. let mut trait_tps = vec::append( @@ -549,7 +549,7 @@ fn mk_ser_method( fn mk_deser_method( cx: ext_ctxt, span: span, - ty: @ast::ty, + ty: @ast::Ty, deser_body: ast::blk ) -> @ast::method { let ty_d = @{ diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 5894758cd85c..5b4cc23ce09f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,7 +1,7 @@ use std::map::HashMap; use parse::parser; use diagnostic::span_handler; -use codemap::{codemap, span, expn_info, expanded_from}; +use codemap::{CodeMap, span, expn_info, expanded_from}; // obsolete old-style #macro code: // @@ -124,7 +124,7 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { // when a macro expansion occurs, the resulting nodes have the backtrace() // -> expn_info of their expansion context stored into their span. trait ext_ctxt { - fn codemap() -> codemap; + fn codemap() -> CodeMap; fn parse_sess() -> parse::parse_sess; fn cfg() -> ast::crate_cfg; fn print_backtrace(); @@ -156,7 +156,7 @@ fn mk_ctxt(parse_sess: parse::parse_sess, mut mod_path: ~[ast::ident], mut trace_mac: bool}; impl ctxt_repr: ext_ctxt { - fn codemap() -> codemap { self.parse_sess.cm } + fn codemap() -> CodeMap { self.parse_sess.cm } fn parse_sess() -> parse::parse_sess { self.parse_sess } fn cfg() -> ast::crate_cfg { self.cfg } fn print_backtrace() { } diff --git a/src/libsyntax/ext/pipes.rs b/src/libsyntax/ext/pipes.rs index ad4984c55582..4d04552bfa15 100644 --- a/src/libsyntax/ext/pipes.rs +++ b/src/libsyntax/ext/pipes.rs @@ -37,7 +37,7 @@ use codemap::span; use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use parse::common::parser_common; use pipes::parse_proto::proto_parser; @@ -52,7 +52,7 @@ fn expand_proto(cx: ext_ctxt, _sp: span, id: ast::ident, let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic, cx.parse_sess().interner, None, tt); let rdr = tt_rdr as reader; - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let proto = rust_parser.parse_proto(cx.str_of(id)); diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 4da9992b0dd3..f10cbc2a5898 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -28,17 +28,17 @@ fn empty_span() -> span { } trait append_types { - fn add_ty(ty: @ast::ty) -> @ast::path; - fn add_tys(+tys: ~[@ast::ty]) -> @ast::path; + fn add_ty(ty: @ast::Ty) -> @ast::path; + fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path; } impl @ast::path: append_types { - fn add_ty(ty: @ast::ty) -> @ast::path { + fn add_ty(ty: @ast::Ty) -> @ast::path { @{types: vec::append_one(self.types, ty), .. *self} } - fn add_tys(+tys: ~[@ast::ty]) -> @ast::path { + fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path { @{types: vec::append(self.types, tys), .. *self} } @@ -47,18 +47,18 @@ impl @ast::path: append_types { trait ext_ctxt_ast_builder { fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound]) -> ast::ty_param; - fn arg(name: ident, ty: @ast::ty) -> ast::arg; + fn arg(name: ident, ty: @ast::Ty) -> ast::arg; fn expr_block(e: @ast::expr) -> ast::blk; - fn fn_decl(+inputs: ~[ast::arg], output: @ast::ty) -> ast::fn_decl; + fn fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl; fn item(name: ident, span: span, +node: ast::item_) -> @ast::item; fn item_fn_poly(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +ty_params: ~[ast::ty_param], +body: ast::blk) -> @ast::item; fn item_fn(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +body: ast::blk) -> @ast::item; fn item_enum_poly(name: ident, span: span, @@ -66,17 +66,17 @@ trait ext_ctxt_ast_builder { +ty_params: ~[ast::ty_param]) -> @ast::item; fn item_enum(name: ident, span: span, +enum_definition: ast::enum_def) -> @ast::item; - fn variant(name: ident, span: span, +tys: ~[@ast::ty]) -> ast::variant; + fn variant(name: ident, span: span, +tys: ~[@ast::Ty]) -> ast::variant; fn item_mod(name: ident, span: span, +items: ~[@ast::item]) -> @ast::item; - fn ty_path_ast_builder(path: @ast::path) -> @ast::ty; + fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty; fn item_ty_poly(name: ident, span: span, - ty: @ast::ty, + ty: @ast::Ty, +params: ~[ast::ty_param]) -> @ast::item; - fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item; - fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty]; - fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field; - fn ty_rec(+v: ~[ast::ty_field]) -> @ast::ty; + fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item; + fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty]; + fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field; + fn ty_rec(+v: ~[ast::ty_field]) -> @ast::Ty; fn field_imm(name: ident, e: @ast::expr) -> ast::field; fn rec(+v: ~[ast::field]) -> @ast::expr; fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk; @@ -84,11 +84,11 @@ trait ext_ctxt_ast_builder { fn stmt_expr(e: @ast::expr) -> @ast::stmt; fn block_expr(b: ast::blk) -> @ast::expr; fn empty_span() -> span; - fn ty_option(ty: @ast::ty) -> @ast::ty; + fn ty_option(ty: @ast::Ty) -> @ast::Ty; } impl ext_ctxt: ext_ctxt_ast_builder { - fn ty_option(ty: @ast::ty) -> @ast::ty { + fn ty_option(ty: @ast::Ty) -> @ast::Ty { self.ty_path_ast_builder(path(~[self.ident_of(~"Option")], self.empty_span()) .add_ty(ty)) @@ -146,18 +146,18 @@ impl ext_ctxt: ext_ctxt_ast_builder { span: self.empty_span()} } - fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field { + fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field { {node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } }, span: self.empty_span()} } - fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::ty { + fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::Ty { @{id: self.next_id(), node: ast::ty_rec(fields), span: self.empty_span()} } - fn ty_infer() -> @ast::ty { + fn ty_infer() -> @ast::Ty { @{id: self.next_id(), node: ast::ty_infer, span: self.empty_span()} @@ -169,7 +169,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { {ident: id, id: self.next_id(), bounds: @bounds} } - fn arg(name: ident, ty: @ast::ty) -> ast::arg { + fn arg(name: ident, ty: @ast::Ty) -> ast::arg { {mode: ast::infer(self.next_id()), ty: ty, ident: name, @@ -192,7 +192,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { } fn fn_decl(+inputs: ~[ast::arg], - output: @ast::ty) -> ast::fn_decl { + output: @ast::Ty) -> ast::fn_decl { {inputs: inputs, output: output, cf: ast::return_val} @@ -224,7 +224,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_fn_poly(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +ty_params: ~[ast::ty_param], +body: ast::blk) -> @ast::item { self.item(name, @@ -237,7 +237,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_fn(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +body: ast::blk) -> @ast::item { self.item_fn_poly(name, inputs, output, ~[], body) } @@ -256,7 +256,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn variant(name: ident, span: span, - +tys: ~[@ast::ty]) -> ast::variant { + +tys: ~[@ast::Ty]) -> ast::variant { let args = tys.map(|ty| {ty: *ty, id: self.next_id()}); {node: {name: name, @@ -278,13 +278,13 @@ impl ext_ctxt: ext_ctxt_ast_builder { items: items})) } - fn ty_path_ast_builder(path: @ast::path) -> @ast::ty { + fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty { @{id: self.next_id(), node: ast::ty_path(path, self.next_id()), span: path.span} } - fn ty_nil_ast_builder() -> @ast::ty { + fn ty_nil_ast_builder() -> @ast::Ty { @{id: self.next_id(), node: ast::ty_nil, span: self.empty_span()} @@ -292,16 +292,16 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_ty_poly(name: ident, span: span, - ty: @ast::ty, + ty: @ast::Ty, +params: ~[ast::ty_param]) -> @ast::item { self.item(name, span, ast::item_ty(ty, params)) } - fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item { + fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item { self.item_ty_poly(name, span, ty, ~[]) } - fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty] { + fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty] { ty_params.map(|p| self.ty_path_ast_builder( path(~[p.ident], self.empty_span()))) } diff --git a/src/libsyntax/ext/pipes/check.rs b/src/libsyntax/ext/pipes/check.rs index 5fcc00ef0121..fcc0c84a4ff3 100644 --- a/src/libsyntax/ext/pipes/check.rs +++ b/src/libsyntax/ext/pipes/check.rs @@ -38,7 +38,7 @@ impl ext_ctxt: proto::visitor<(), (), ()> { } } - fn visit_message(name: ~str, _span: span, _tys: &[@ast::ty], + fn visit_message(name: ~str, _span: span, _tys: &[@ast::Ty], this: state, next: next_state) { match next { Some({state: next, tys: next_tys}) => { @@ -68,4 +68,4 @@ impl ext_ctxt: proto::visitor<(), (), ()> { None => () } } -} \ No newline at end of file +} diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs index 5c15b616b4ae..8f2b92a720c0 100644 --- a/src/libsyntax/ext/pipes/parse_proto.rs +++ b/src/libsyntax/ext/pipes/parse_proto.rs @@ -10,7 +10,7 @@ trait proto_parser { fn parse_state(proto: protocol); } -impl parser: proto_parser { +impl parser::Parser: proto_parser { fn parse_proto(id: ~str) -> protocol { let proto = protocol(id, self.span); diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 874ea01e9b01..7e1cbe9ad0db 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -181,7 +181,7 @@ impl message: gen_send { } } - fn to_ty(cx: ext_ctxt) -> @ast::ty { + fn to_ty(cx: ext_ctxt) -> @ast::Ty { cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span()) .add_tys(cx.ty_vars(self.get_params()))) } @@ -360,7 +360,7 @@ impl protocol: gen_init { }} } - fn buffer_ty_path(cx: ext_ctxt) -> @ast::ty { + fn buffer_ty_path(cx: ext_ctxt) -> @ast::Ty { let mut params: ~[ast::ty_param] = ~[]; for (copy self.states).each |s| { for s.ty_params.each |tp| { @@ -444,13 +444,13 @@ impl ~[@ast::item]: to_source { } } -impl @ast::ty: to_source { +impl @ast::Ty: to_source { fn to_source(cx: ext_ctxt) -> ~str { ty_to_str(self, cx.parse_sess().interner) } } -impl ~[@ast::ty]: to_source { +impl ~[@ast::Ty]: to_source { fn to_source(cx: ext_ctxt) -> ~str { str::connect(self.map(|i| i.to_source(cx)), ~", ") } diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index a501df4c32d2..229e55fdfcc6 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -35,11 +35,11 @@ impl direction { } } -type next_state = Option<{state: ~str, tys: ~[@ast::ty]}>; +type next_state = Option<{state: ~str, tys: ~[@ast::Ty]}>; enum message { // name, span, data, current state, next state - message(~str, span, ~[@ast::ty], state, next_state) + message(~str, span, ~[@ast::Ty], state, next_state) } impl message { @@ -78,7 +78,7 @@ enum state { impl state { fn add_message(name: ~str, span: span, - +data: ~[@ast::ty], next: next_state) { + +data: ~[@ast::Ty], next: next_state) { self.messages.push(message(name, span, data, self, next)); } @@ -92,7 +92,7 @@ impl state { } /// Returns the type that is used for the messages. - fn to_ty(cx: ext_ctxt) -> @ast::ty { + fn to_ty(cx: ext_ctxt) -> @ast::Ty { cx.ty_path_ast_builder (path(~[cx.ident_of(self.name)],self.span).add_tys( cx.ty_vars(self.ty_params))) @@ -200,7 +200,7 @@ impl protocol { trait visitor { fn visit_proto(proto: protocol, st: &[Tstate]) -> Tproto; fn visit_state(state: state, m: &[Tmessage]) -> Tstate; - fn visit_message(name: ~str, spane: span, tys: &[@ast::ty], + fn visit_message(name: ~str, spane: span, tys: &[@ast::Ty], this: state, next: next_state) -> Tmessage; } diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs index ee9602598d1e..a83789642ccc 100644 --- a/src/libsyntax/ext/qquote.rs +++ b/src/libsyntax/ext/qquote.rs @@ -1,7 +1,7 @@ use ast::{crate, expr_, mac_invoc, mac_aq, mac_var}; use parse::parser; -use parse::parser::parse_from_source_str; +use parse::parser::{Parser, parse_from_source_str}; use dvec::DVec; use parse::token::ident_interner; @@ -24,7 +24,7 @@ struct gather_item { type aq_ctxt = @{lo: uint, gather: DVec}; enum fragment { from_expr(@ast::expr), - from_ty(@ast::ty) + from_ty(@ast::Ty) } fn ids_ext(cx: ext_ctxt, strs: ~[~str]) -> ~[ast::ident] { @@ -68,7 +68,7 @@ impl @ast::expr: qq_helper { } fn get_fold_fn() -> ~str {~"fold_expr"} } -impl @ast::ty: qq_helper { +impl @ast::Ty: qq_helper { fn span() -> span {self.span} fn visit(cx: aq_ctxt, v: vt) {visit_ty(self, cx, v);} fn extract_mac() -> Option { @@ -186,13 +186,13 @@ fn expand_ast(ecx: ext_ctxt, _sp: span, }; } -fn parse_crate(p: parser) -> @ast::crate { p.parse_crate_mod(~[]) } -fn parse_ty(p: parser) -> @ast::ty { p.parse_ty(false) } -fn parse_stmt(p: parser) -> @ast::stmt { p.parse_stmt(~[]) } -fn parse_expr(p: parser) -> @ast::expr { p.parse_expr() } -fn parse_pat(p: parser) -> @ast::pat { p.parse_pat(true) } +fn parse_crate(p: Parser) -> @ast::crate { p.parse_crate_mod(~[]) } +fn parse_ty(p: Parser) -> @ast::Ty { p.parse_ty(false) } +fn parse_stmt(p: Parser) -> @ast::stmt { p.parse_stmt(~[]) } +fn parse_expr(p: Parser) -> @ast::expr { p.parse_expr() } +fn parse_pat(p: Parser) -> @ast::pat { p.parse_pat(true) } -fn parse_item(p: parser) -> @ast::item { +fn parse_item(p: Parser) -> @ast::item { match p.parse_item(~[]) { Some(item) => item, None => fail ~"parse_item: parsing an item failed" @@ -200,7 +200,7 @@ fn parse_item(p: parser) -> @ast::item { } fn finish - (ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: parser) -> T) + (ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: Parser) -> T) -> @ast::expr { let cm = ecx.codemap(); @@ -309,7 +309,7 @@ fn fold_crate(f: ast_fold, &&n: @ast::crate) -> @ast::crate { @f.fold_crate(*n) } fn fold_expr(f: ast_fold, &&n: @ast::expr) -> @ast::expr {f.fold_expr(n)} -fn fold_ty(f: ast_fold, &&n: @ast::ty) -> @ast::ty {f.fold_ty(n)} +fn fold_ty(f: ast_fold, &&n: @ast::Ty) -> @ast::Ty {f.fold_ty(n)} fn fold_item(f: ast_fold, &&n: @ast::item) -> @ast::item { f.fold_item(n).get() //HACK: we know we don't drop items } diff --git a/src/libsyntax/ext/simplext.rs b/src/libsyntax/ext/simplext.rs index e16e1c553499..bec29c9a8354 100644 --- a/src/libsyntax/ext/simplext.rs +++ b/src/libsyntax/ext/simplext.rs @@ -6,7 +6,7 @@ use base::*; use fold::*; use ast_util::respan; -use ast::{ident, path, ty, blk_, expr, expr_path, +use ast::{ident, path, Ty, blk_, expr, expr_path, expr_vec, expr_mac, mac_invoc, node_id, expr_index}; export add_new_extension; @@ -29,7 +29,7 @@ enum matchable { match_expr(@expr), match_path(@path), match_ident(ast::spanned), - match_ty(@ty), + match_ty(@Ty), match_block(ast::blk), match_exact, /* don't bind anything, just verify the AST traversal */ } diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index c2d4de1b423c..0c7d408db7cc 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -2,7 +2,7 @@ use codemap::span; use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use parse::common::parser_common; fn expand_trace_macros(cx: ext_ctxt, sp: span, @@ -13,7 +13,7 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span, let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic, cx.parse_sess().interner, None, tt); let rdr = tt_rdr as reader; - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let arg = cx.str_of(rust_parser.parse_ident()); match arg { @@ -21,7 +21,7 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span, ~"false" => cx.set_trace_macros(false), _ => cx.span_fatal(sp, ~"trace_macros! only accepts `true` or `false`") } - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let result = rust_parser.parse_expr(); base::mr_expr(result) } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 0b2070c8c86d..17122b85fb36 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -1,9 +1,9 @@ // Earley-like parser for macros. use parse::token; -use parse::token::{token, EOF, to_str, nonterminal}; +use parse::token::{Token, EOF, to_str, nonterminal}; use parse::lexer::*; //resolve bug? //import parse::lexer::{reader, tt_reader, tt_reader_as_reader}; -use parse::parser::{parser,SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; //import parse::common::parser_common; use parse::common::*; //resolve bug? use parse::parse_sess; @@ -97,7 +97,7 @@ fn is_some(&&mpu: matcher_pos_up) -> bool { type matcher_pos = ~{ elts: ~[ast::matcher], // maybe should be /&? Need to understand regions. - sep: Option, + sep: Option, mut idx: uint, mut up: matcher_pos_up, // mutable for swapping only matches: ~[DVec<@named_match>], @@ -122,7 +122,7 @@ fn count_names(ms: &[matcher]) -> uint { } #[allow(non_implicitly_copyable_typarams)] -fn initial_matcher_pos(ms: ~[matcher], sep: Option, lo: uint) +fn initial_matcher_pos(ms: ~[matcher], sep: Option, lo: uint) -> matcher_pos { let mut match_idx_hi = 0u; for ms.each() |elt| { @@ -354,7 +354,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) } rdr.next_token(); } else /* bb_eis.len() == 1 */ { - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let ei = bb_eis.pop(); match ei.elts[ei.idx].node { @@ -381,7 +381,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) } } -fn parse_nt(p: parser, name: ~str) -> nonterminal { +fn parse_nt(p: Parser, name: ~str) -> nonterminal { match name { ~"item" => match p.parse_item(~[]) { Some(i) => token::nt_item(i), diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 52369ad7207f..31bc375a76d5 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -4,7 +4,7 @@ use ast::{ident, matcher_, matcher, match_tok, match_nonterminal, match_seq, tt_delim}; use parse::lexer::{new_tt_reader, reader}; use parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use macro_parser::{parse, parse_or_else, success, failure, named_match, matched_seq, matched_nonterminal, error}; use std::map::HashMap; @@ -86,7 +86,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, // rhs has holes ( `$id` and `$(...)` that need filled) let trncbr = new_tt_reader(s_d, itr, Some(named_matches), ~[rhs]); - let p = parser(cx.parse_sess(), cx.cfg(), + let p = Parser(cx.parse_sess(), cx.cfg(), trncbr as reader, SOURCE_FILE); let e = p.parse_expr(); return mr_expr(e); @@ -111,4 +111,4 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, name: *cx.parse_sess().interner.get(name), ext: expr_tt({expander: exp, span: Some(sp)}) }); -} \ No newline at end of file +} diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index a8a41cca6cbd..238f9db6ac53 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -2,8 +2,7 @@ use diagnostic::span_handler; use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,ident}; use macro_parser::{named_match, matched_seq, matched_nonterminal}; use codemap::span; -use parse::token::{EOF, INTERPOLATED, IDENT, token, nt_ident, - ident_interner}; +use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner}; use std::map::HashMap; export tt_reader, new_tt_reader, dup_tt_reader, tt_next_token; @@ -19,7 +18,7 @@ type tt_frame = @{ readme: ~[ast::token_tree], mut idx: uint, dotdotdoted: bool, - sep: Option, + sep: Option, up: tt_frame_up, }; @@ -32,7 +31,7 @@ type tt_reader = @{ mut repeat_idx: ~[uint], mut repeat_len: ~[uint], /* cached: */ - mut cur_tok: token, + mut cur_tok: Token, mut cur_span: span }; @@ -134,7 +133,7 @@ fn lockstep_iter_size(t: token_tree, r: tt_reader) -> lis { } -fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} { +fn tt_next_token(&&r: tt_reader) -> {tok: Token, sp: span} { let ret_val = { tok: r.cur_tok, sp: r.cur_span }; while r.cur.idx >= r.cur.readme.len() { /* done with this set; pop or repeat? */ diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 68d9cd80430d..564debefa253 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -33,7 +33,7 @@ trait ast_fold { fn fold_pat(&&v: @pat) -> @pat; fn fold_decl(&&v: @decl) -> @decl; fn fold_expr(&&v: @expr) -> @expr; - fn fold_ty(&&v: @ty) -> @ty; + fn fold_ty(&&v: @Ty) -> @Ty; fn fold_mod(_mod) -> _mod; fn fold_foreign_mod(foreign_mod) -> foreign_mod; fn fold_variant(variant) -> variant; @@ -728,7 +728,7 @@ impl ast_fold_precursor: ast_fold { node: n, span: self.new_span(s)}; } - fn fold_ty(&&x: @ty) -> @ty { + fn fold_ty(&&x: @Ty) -> @Ty { let (n, s) = self.fold_ty(x.node, x.span, self as ast_fold); return @{id: self.new_id(x.id), node: n, span: self.new_span(s)}; } diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs index 2c04b2a14190..e38ee7ff0376 100644 --- a/src/libsyntax/parse.rs +++ b/src/libsyntax/parse.rs @@ -12,7 +12,7 @@ export parse_expr_from_source_str, parse_item_from_source_str; export parse_stmt_from_source_str; export parse_from_source_str; -use parser::parser; +use parser::Parser; use attr::parser_attr; use common::parser_common; use ast::node_id; @@ -22,7 +22,7 @@ use lexer::{reader, string_reader}; use parse::token::{ident_interner, mk_ident_interner}; type parse_sess = @{ - cm: codemap::codemap, + cm: codemap::CodeMap, mut next_id: node_id, span_diagnostic: span_handler, interner: @ident_interner, @@ -40,7 +40,7 @@ fn new_parse_sess(demitter: Option) -> parse_sess { mut chpos: 0u, mut byte_pos: 0u}; } -fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::codemap) +fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::CodeMap) -> parse_sess { return @{cm: cm, mut next_id: 1, @@ -142,7 +142,7 @@ fn parse_stmt_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg, return r; } -fn parse_from_source_str(f: fn (p: parser) -> T, +fn parse_from_source_str(f: fn (p: Parser) -> T, name: ~str, ss: codemap::file_substr, source: @~str, cfg: ast::crate_cfg, sess: parse_sess) @@ -170,19 +170,19 @@ fn next_node_id(sess: parse_sess) -> node_id { fn new_parser_etc_from_source_str(sess: parse_sess, cfg: ast::crate_cfg, +name: ~str, +ss: codemap::file_substr, - source: @~str) -> (parser, string_reader) { + source: @~str) -> (Parser, string_reader) { let ftype = parser::SOURCE_FILE; let filemap = codemap::new_filemap_w_substr (name, ss, source, sess.chpos, sess.byte_pos); sess.cm.files.push(filemap); let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap, sess.interner); - return (parser(sess, cfg, srdr as reader, ftype), srdr); + return (Parser(sess, cfg, srdr as reader, ftype), srdr); } fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg, +name: ~str, +ss: codemap::file_substr, - source: @~str) -> parser { + source: @~str) -> Parser { let (p, _) = new_parser_etc_from_source_str(sess, cfg, name, ss, source); move p } @@ -190,7 +190,7 @@ fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg, fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: &Path, ftype: parser::file_type) -> - (parser, string_reader) { + (Parser, string_reader) { let res = io::read_whole_file_str(path); match res { result::Ok(_) => { /* Continue. */ } @@ -202,18 +202,18 @@ fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg, sess.cm.files.push(filemap); let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap, sess.interner); - return (parser(sess, cfg, srdr as reader, ftype), srdr); + return (Parser(sess, cfg, srdr as reader, ftype), srdr); } fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: &Path, - ftype: parser::file_type) -> parser { + ftype: parser::file_type) -> Parser { let (p, _) = new_parser_etc_from_file(sess, cfg, path, ftype); move p } fn new_parser_from_tt(sess: parse_sess, cfg: ast::crate_cfg, - tt: ~[ast::token_tree]) -> parser { + tt: ~[ast::token_tree]) -> Parser { let trdr = lexer::new_tt_reader(sess.span_diagnostic, sess.interner, None, tt); - return parser(sess, cfg, trdr as reader, parser::SOURCE_FILE) + return Parser(sess, cfg, trdr as reader, parser::SOURCE_FILE) } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 9be4909814b1..42101a431d6c 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -23,7 +23,7 @@ trait parser_attr { fn parse_optional_meta() -> ~[@ast::meta_item]; } -impl parser: parser_attr { +impl Parser: parser_attr { fn parse_outer_attrs_or_ext(first_item_attrs: ~[ast::attribute]) -> attr_or_ext diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index c8c30ee7fa9c..50c22c08f4f8 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -1,63 +1,63 @@ use std::map::{HashMap}; use ast_util::spanned; -use parser::parser; +use parser::Parser; use lexer::reader; type seq_sep = { - sep: Option, + sep: Option, trailing_sep_allowed: bool }; -fn seq_sep_trailing_disallowed(t: token::token) -> seq_sep { +fn seq_sep_trailing_disallowed(t: token::Token) -> seq_sep { return {sep: option::Some(t), trailing_sep_allowed: false}; } -fn seq_sep_trailing_allowed(t: token::token) -> seq_sep { +fn seq_sep_trailing_allowed(t: token::Token) -> seq_sep { return {sep: option::Some(t), trailing_sep_allowed: true}; } fn seq_sep_none() -> seq_sep { return {sep: option::None, trailing_sep_allowed: false}; } -fn token_to_str(reader: reader, ++token: token::token) -> ~str { +fn token_to_str(reader: reader, ++token: token::Token) -> ~str { token::to_str(reader.interner(), token) } trait parser_common { - fn unexpected_last(t: token::token) -> !; + fn unexpected_last(t: token::Token) -> !; fn unexpected() -> !; - fn expect(t: token::token); + fn expect(t: token::Token); fn parse_ident() -> ast::ident; fn parse_path_list_ident() -> ast::path_list_ident; fn parse_value_ident() -> ast::ident; - fn eat(tok: token::token) -> bool; + fn eat(tok: token::Token) -> bool; // A sanity check that the word we are asking for is a known keyword fn require_keyword(word: ~str); - fn token_is_keyword(word: ~str, ++tok: token::token) -> bool; + fn token_is_keyword(word: ~str, ++tok: token::Token) -> bool; fn is_keyword(word: ~str) -> bool; - fn is_any_keyword(tok: token::token) -> bool; + fn is_any_keyword(tok: token::Token) -> bool; fn eat_keyword(word: ~str) -> bool; fn expect_keyword(word: ~str); fn expect_gt(); - fn parse_seq_to_before_gt(sep: Option, - f: fn(parser) -> T) -> ~[T]; - fn parse_seq_to_gt(sep: Option, - f: fn(parser) -> T) -> ~[T]; - fn parse_seq_lt_gt(sep: Option, - f: fn(parser) -> T) -> spanned<~[T]>; - fn parse_seq_to_end(ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T]; - fn parse_seq_to_before_end(ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T]; - fn parse_unspanned_seq(bra: token::token, - ket: token::token, + fn parse_seq_to_before_gt(sep: Option, + f: fn(Parser) -> T) -> ~[T]; + fn parse_seq_to_gt(sep: Option, + f: fn(Parser) -> T) -> ~[T]; + fn parse_seq_lt_gt(sep: Option, + f: fn(Parser) -> T) -> spanned<~[T]>; + fn parse_seq_to_end(ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> ~[T]; + fn parse_seq_to_before_end(ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> ~[T]; + fn parse_unspanned_seq(bra: token::Token, + ket: token::Token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T]; - fn parse_seq(bra: token::token, ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> spanned<~[T]>; + f: fn(Parser) -> T) -> ~[T]; + fn parse_seq(bra: token::Token, ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> spanned<~[T]>; } -impl parser: parser_common { - fn unexpected_last(t: token::token) -> ! { +impl Parser: parser_common { + fn unexpected_last(t: token::Token) -> ! { self.span_fatal( copy self.last_span, ~"unexpected token: `" + token_to_str(self.reader, t) + ~"`"); @@ -68,7 +68,7 @@ impl parser: parser_common { + token_to_str(self.reader, self.token) + ~"`"); } - fn expect(t: token::token) { + fn expect(t: token::Token) { if self.token == t { self.bump(); } else { @@ -104,7 +104,7 @@ impl parser: parser_common { return self.parse_ident(); } - fn eat(tok: token::token) -> bool { + fn eat(tok: token::Token) -> bool { return if self.token == tok { self.bump(); true } else { false }; } @@ -117,14 +117,14 @@ impl parser: parser_common { } } - fn token_is_word(word: ~str, ++tok: token::token) -> bool { + fn token_is_word(word: ~str, ++tok: token::Token) -> bool { match tok { token::IDENT(sid, false) => { *self.id_to_str(sid) == word } _ => { false } } } - fn token_is_keyword(word: ~str, ++tok: token::token) -> bool { + fn token_is_keyword(word: ~str, ++tok: token::Token) -> bool { self.require_keyword(word); self.token_is_word(word, tok) } @@ -133,7 +133,7 @@ impl parser: parser_common { self.token_is_keyword(word, self.token) } - fn is_any_keyword(tok: token::token) -> bool { + fn is_any_keyword(tok: token::Token) -> bool { match tok { token::IDENT(sid, false) => { self.keywords.contains_key_ref(self.id_to_str(sid)) @@ -216,8 +216,8 @@ impl parser: parser_common { } } - fn parse_seq_to_before_gt(sep: Option, - f: fn(parser) -> T) -> ~[T] { + fn parse_seq_to_before_gt(sep: Option, + f: fn(Parser) -> T) -> ~[T] { let mut first = true; let mut v = ~[]; while self.token != token::GT @@ -235,16 +235,16 @@ impl parser: parser_common { return v; } - fn parse_seq_to_gt(sep: Option, - f: fn(parser) -> T) -> ~[T] { + fn parse_seq_to_gt(sep: Option, + f: fn(Parser) -> T) -> ~[T] { let v = self.parse_seq_to_before_gt(sep, f); self.expect_gt(); return v; } - fn parse_seq_lt_gt(sep: Option, - f: fn(parser) -> T) -> spanned<~[T]> { + fn parse_seq_lt_gt(sep: Option, + f: fn(Parser) -> T) -> spanned<~[T]> { let lo = self.span.lo; self.expect(token::LT); let result = self.parse_seq_to_before_gt::(sep, f); @@ -253,16 +253,16 @@ impl parser: parser_common { return spanned(lo, hi, result); } - fn parse_seq_to_end(ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T] { + fn parse_seq_to_end(ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> ~[T] { let val = self.parse_seq_to_before_end(ket, sep, f); self.bump(); return val; } - fn parse_seq_to_before_end(ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T] { + fn parse_seq_to_before_end(ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> ~[T] { let mut first: bool = true; let mut v: ~[T] = ~[]; while self.token != ket { @@ -279,10 +279,10 @@ impl parser: parser_common { return v; } - fn parse_unspanned_seq(bra: token::token, - ket: token::token, + fn parse_unspanned_seq(bra: token::Token, + ket: token::Token, sep: seq_sep, - f: fn(parser) -> T) -> ~[T] { + f: fn(Parser) -> T) -> ~[T] { self.expect(bra); let result = self.parse_seq_to_before_end::(ket, sep, f); self.bump(); @@ -291,8 +291,8 @@ impl parser: parser_common { // NB: Do not use this function unless you actually plan to place the // spanned list in the AST. - fn parse_seq(bra: token::token, ket: token::token, sep: seq_sep, - f: fn(parser) -> T) -> spanned<~[T]> { + fn parse_seq(bra: token::Token, ket: token::Token, sep: seq_sep, + f: fn(Parser) -> T) -> spanned<~[T]> { let lo = self.span.lo; self.expect(bra); let result = self.parse_seq_to_before_end::(ket, sep, f); diff --git a/src/libsyntax/parse/eval.rs b/src/libsyntax/parse/eval.rs index c91060284910..56c9d4de9f3c 100644 --- a/src/libsyntax/parse/eval.rs +++ b/src/libsyntax/parse/eval.rs @@ -1,4 +1,4 @@ -use parser::{parser, SOURCE_FILE}; +use parser::{Parser, SOURCE_FILE}; use attr::parser_attr; export eval_crate_directives_to_mod; diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 06fcc1cf9589..8f57d733eb51 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -10,11 +10,11 @@ export string_reader_as_reader, tt_reader_as_reader; trait reader { fn is_eof() -> bool; - fn next_token() -> {tok: token::token, sp: span}; + fn next_token() -> {tok: token::Token, sp: span}; fn fatal(~str) -> !; fn span_diag() -> span_handler; pure fn interner() -> @token::ident_interner; - fn peek() -> {tok: token::token, sp: span}; + fn peek() -> {tok: token::Token, sp: span}; fn dup() -> reader; } @@ -28,7 +28,7 @@ type string_reader = @{ filemap: codemap::filemap, interner: @token::ident_interner, /* cached: */ - mut peek_tok: token::token, + mut peek_tok: token::Token, mut peek_span: span }; @@ -69,7 +69,7 @@ fn dup_string_reader(&&r: string_reader) -> string_reader { impl string_reader: reader { fn is_eof() -> bool { is_eof(self) } - fn next_token() -> {tok: token::token, sp: span} { + fn next_token() -> {tok: token::Token, sp: span} { let ret_val = {tok: self.peek_tok, sp: self.peek_span}; string_advance_token(self); return ret_val; @@ -79,7 +79,7 @@ impl string_reader: reader { } fn span_diag() -> span_handler { self.span_diagnostic } pure fn interner() -> @token::ident_interner { self.interner } - fn peek() -> {tok: token::token, sp: span} { + fn peek() -> {tok: token::Token, sp: span} { {tok: self.peek_tok, sp: self.peek_span} } fn dup() -> reader { dup_string_reader(self) as reader } @@ -87,7 +87,7 @@ impl string_reader: reader { impl tt_reader: reader { fn is_eof() -> bool { self.cur_tok == token::EOF } - fn next_token() -> {tok: token::token, sp: span} { + fn next_token() -> {tok: token::Token, sp: span} { /* weird resolve bug: if the following `if`, or any of its statements are removed, we get resolution errors */ if false { @@ -101,7 +101,7 @@ impl tt_reader: reader { } fn span_diag() -> span_handler { self.sp_diag } pure fn interner() -> @token::ident_interner { self.interner } - fn peek() -> {tok: token::token, sp: span} { + fn peek() -> {tok: token::Token, sp: span} { { tok: self.cur_tok, sp: self.cur_span } } fn dup() -> reader { dup_tt_reader(self) as reader } @@ -196,14 +196,14 @@ fn is_bin_digit(c: char) -> bool { return c == '0' || c == '1'; } // might return a sugared-doc-attr fn consume_whitespace_and_comments(rdr: string_reader) - -> Option<{tok: token::token, sp: span}> { + -> Option<{tok: token::Token, sp: span}> { while is_whitespace(rdr.curr) { bump(rdr); } return consume_any_line_comment(rdr); } // might return a sugared-doc-attr fn consume_any_line_comment(rdr: string_reader) - -> Option<{tok: token::token, sp: span}> { + -> Option<{tok: token::Token, sp: span}> { if rdr.curr == '/' { match nextch(rdr) { '/' => { @@ -246,7 +246,7 @@ fn consume_any_line_comment(rdr: string_reader) // might return a sugared-doc-attr fn consume_block_comment(rdr: string_reader) - -> Option<{tok: token::token, sp: span}> { + -> Option<{tok: token::Token, sp: span}> { // block comments starting with "/**" or "/*!" are doc-comments if rdr.curr == '*' || rdr.curr == '!' { @@ -317,7 +317,7 @@ fn scan_digits(rdr: string_reader, radix: uint) -> ~str { }; } -fn scan_number(c: char, rdr: string_reader) -> token::token { +fn scan_number(c: char, rdr: string_reader) -> token::Token { let mut num_str, base = 10u, c = c, n = nextch(rdr); if c == '0' && n == 'x' { bump(rdr); @@ -435,7 +435,7 @@ fn scan_numeric_escape(rdr: string_reader, n_hex_digits: uint) -> char { return accum_int as char; } -fn next_token_inner(rdr: string_reader) -> token::token { +fn next_token_inner(rdr: string_reader) -> token::Token { let mut accum_str = ~""; let mut c = rdr.curr; if (c >= 'a' && c <= 'z') @@ -460,7 +460,7 @@ fn next_token_inner(rdr: string_reader) -> token::token { if is_dec_digit(c) { return scan_number(c, rdr); } - fn binop(rdr: string_reader, op: token::binop) -> token::token { + fn binop(rdr: string_reader, op: token::binop) -> token::Token { bump(rdr); if rdr.curr == '=' { bump(rdr); diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 828d498ca3c2..c0e01fb19443 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -10,7 +10,7 @@ removed. use codemap::span; use ast::{expr, expr_lit, lit_nil}; use ast_util::{respan}; -use token::token; +use token::Token; /// The specific types of unsupported syntax pub enum ObsoleteSyntax { @@ -47,7 +47,7 @@ pub trait ObsoleteReporter { fn obsolete_expr(sp: span, kind: ObsoleteSyntax) -> @expr; } -impl parser : ObsoleteReporter { +impl Parser : ObsoleteReporter { /// Reports an obsolete syntax non-fatal error. fn obsolete(sp: span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { @@ -121,7 +121,7 @@ impl parser : ObsoleteReporter { } } - fn token_is_obsolete_ident(ident: &str, token: token) -> bool { + fn token_is_obsolete_ident(ident: &str, token: Token) -> bool { match token { token::IDENT(copy sid, _) => { str::eq_slice(*self.id_to_str(sid), ident) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 973822ddff9b..e29620a7e79d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6,7 +6,7 @@ use std::map::HashMap; use token::{can_begin_expr, is_ident, is_ident_or_path, is_plain_ident, INTERPOLATED, special_idents}; use codemap::{span,fss_none}; -use util::interner::interner; +use util::interner::Interner; use ast_util::{spanned, respan, mk_sp, ident_to_path, operator_prec}; use lexer::reader; use prec::{as_prec, token_to_binop}; @@ -58,7 +58,7 @@ use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, stmt_semi, struct_def, struct_field, struct_variant_kind, subtract, sty_box, sty_by_ref, sty_region, sty_static, sty_uniq, sty_value, token_tree, trait_method, trait_ref, tt_delim, tt_seq, - tt_tok, tt_nonterminal, tuple_variant_kind, ty, ty_, ty_bot, + tt_tok, tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box, ty_field, ty_fn, ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length, type_value_ns, @@ -71,7 +71,7 @@ use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, expr_vstore_uniq}; export file_type; -export parser; +export Parser; export CRATE_FILE; export SOURCE_FILE; @@ -190,14 +190,14 @@ pure fn maybe_append(+lhs: ~[attribute], rhs: Option<~[attribute]>) /* ident is handled by common.rs */ -fn parser(sess: parse_sess, cfg: ast::crate_cfg, - +rdr: reader, ftype: file_type) -> parser { +fn Parser(sess: parse_sess, cfg: ast::crate_cfg, + +rdr: reader, ftype: file_type) -> Parser { let tok0 = rdr.next_token(); let span0 = tok0.sp; let interner = rdr.interner(); - parser { + Parser { reader: move rdr, interner: move interner, sess: sess, @@ -223,14 +223,14 @@ fn parser(sess: parse_sess, cfg: ast::crate_cfg, } } -struct parser { +struct Parser { sess: parse_sess, cfg: crate_cfg, file_type: file_type, - mut token: token::token, + mut token: token::Token, mut span: span, mut last_span: span, - mut buffer: [mut {tok: token::token, sp: span}]/4, + mut buffer: [mut {tok: token::Token, sp: span}]/4, mut buffer_start: int, mut buffer_end: int, mut restriction: restriction, @@ -247,7 +247,7 @@ struct parser { drop {} /* do not copy the parser; its state is tied to outside state */ } -impl parser { +impl Parser { fn bump() { self.last_span = self.span; let next = if self.buffer_start == self.buffer_end { @@ -260,7 +260,7 @@ impl parser { self.token = next.tok; self.span = next.sp; } - fn swap(next: token::token, lo: uint, hi: uint) { + fn swap(next: token::Token, lo: uint, hi: uint) { self.token = next; self.span = mk_sp(lo, hi); } @@ -270,7 +270,7 @@ impl parser { } return (4 - self.buffer_start) + self.buffer_end; } - fn look_ahead(distance: uint) -> token::token { + fn look_ahead(distance: uint) -> token::Token { let dist = distance as int; while self.buffer_length() < dist { self.buffer[self.buffer_end] = self.reader.next_token(); @@ -411,7 +411,7 @@ impl parser { }); } - fn parse_ret_ty() -> (ret_style, @ty) { + fn parse_ret_ty() -> (ret_style, @Ty) { return if self.eat(token::RARROW) { let lo = self.span.lo; if self.eat(token::NOT) { @@ -472,7 +472,7 @@ impl parser { self.region_from_name(name) } - fn parse_ty(colons_before_params: bool) -> @ty { + fn parse_ty(colons_before_params: bool) -> @Ty { maybe_whole!(self, nt_ty); let lo = self.span.lo; @@ -609,10 +609,10 @@ impl parser { } } - fn parse_capture_item_or(parse_arg_fn: fn(parser) -> arg_or_capture_item) + fn parse_capture_item_or(parse_arg_fn: fn(Parser) -> arg_or_capture_item) -> arg_or_capture_item { - fn parse_capture_item(p:parser, is_move: bool) -> capture_item { + fn parse_capture_item(p:Parser, is_move: bool) -> capture_item { let sp = mk_sp(p.span.lo, p.span.hi); let ident = p.parse_ident(); @{id: p.get_id(), is_move: is_move, name: ident, span: sp} @@ -728,7 +728,7 @@ impl parser { } } - fn lit_from_token(tok: token::token) -> lit_ { + fn lit_from_token(tok: token::Token) -> lit_ { match tok { token::LIT_INT(i, it) => lit_int(i, it), token::LIT_UINT(u, ut) => lit_uint(u, ut), @@ -760,8 +760,8 @@ impl parser { } fn parse_path_without_tps_( - parse_ident: fn(parser) -> ident, - parse_last_ident: fn(parser) -> ident) -> @path { + parse_ident: fn(Parser) -> ident, + parse_last_ident: fn(Parser) -> ident) -> @path { maybe_whole!(self, nt_path); let lo = self.span.lo; @@ -842,7 +842,7 @@ impl parser { } } - fn parse_field(sep: token::token) -> field { + fn parse_field(sep: token::Token) -> field { let lo = self.span.lo; let m = self.parse_mutability(); let i = self.parse_ident(); @@ -1220,7 +1220,7 @@ impl parser { return e; } - fn parse_sep_and_zerok() -> (Option, bool) { + fn parse_sep_and_zerok() -> (Option, bool) { if self.token == token::BINOP(token::STAR) || self.token == token::BINOP(token::PLUS) { let zerok = self.token == token::BINOP(token::STAR); @@ -1243,7 +1243,7 @@ impl parser { fn parse_token_tree() -> token_tree { maybe_whole!(deref self, nt_tt); - fn parse_tt_tok(p: parser, delim_ok: bool) -> token_tree { + fn parse_tt_tok(p: Parser, delim_ok: bool) -> token_tree { match p.token { token::RPAREN | token::RBRACE | token::RBRACKET if !delim_ok => { @@ -1310,8 +1310,8 @@ impl parser { // This goofy function is necessary to correctly match parens in matchers. // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be // invalid. It's similar to common::parse_seq. - fn parse_matcher_subseq(name_idx: @mut uint, bra: token::token, - ket: token::token) -> ~[matcher] { + fn parse_matcher_subseq(name_idx: @mut uint, bra: token::Token, + ket: token::Token) -> ~[matcher] { let mut ret_val = ~[]; let mut lparens = 0u; @@ -2158,7 +2158,7 @@ impl parser { fn parse_stmt(+first_item_attrs: ~[attribute]) -> @stmt { maybe_whole!(self, nt_stmt); - fn check_expected_item(p: parser, current_attrs: ~[attribute]) { + fn check_expected_item(p: Parser, current_attrs: ~[attribute]) { // If we have attributes then we should have an item if vec::is_not_empty(current_attrs) { p.fatal(~"expected item"); @@ -2221,7 +2221,7 @@ impl parser { maybe_whole!(pair_empty self, nt_block); - fn maybe_parse_inner_attrs_and_next(p: parser, parse_attrs: bool) -> + fn maybe_parse_inner_attrs_and_next(p: Parser, parse_attrs: bool) -> {inner: ~[attribute], next: ~[attribute]} { if parse_attrs { p.parse_inner_attrs_and_next() @@ -2386,7 +2386,7 @@ impl parser { } else { ~[] } } - fn parse_fn_decl(parse_arg_fn: fn(parser) -> arg_or_capture_item) + fn parse_fn_decl(parse_arg_fn: fn(Parser) -> arg_or_capture_item) -> (fn_decl, capture_clause) { let args_or_capture_items: ~[arg_or_capture_item] = @@ -2420,11 +2420,11 @@ impl parser { } fn parse_fn_decl_with_self(parse_arg_fn: - fn(parser) -> arg_or_capture_item) + fn(Parser) -> arg_or_capture_item) -> (self_ty, fn_decl, capture_clause) { fn maybe_parse_self_ty(cnstr: fn(+v: mutability) -> ast::self_ty_, - p: parser) -> ast::self_ty_ { + p: Parser) -> ast::self_ty_ { // We need to make sure it isn't a mode or a type if p.token_is_keyword(~"self", p.look_ahead(1)) || ((p.token_is_keyword(~"const", p.look_ahead(1)) || @@ -2604,7 +2604,7 @@ impl parser { // Parses four variants (with the region/type params always optional): // impl ~[T] : to_str { ... } fn parse_item_impl() -> item_info { - fn wrap_path(p: parser, pt: @path) -> @ty { + fn wrap_path(p: Parser, pt: @path) -> @Ty { @{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span} } @@ -2664,7 +2664,7 @@ impl parser { ref_id: self.get_id(), impl_id: self.get_id()} } - fn parse_trait_ref_list(ket: token::token) -> ~[@trait_ref] { + fn parse_trait_ref_list(ket: token::Token) -> ~[@trait_ref] { self.parse_seq_to_before_end( ket, seq_sep_trailing_disallowed(token::COMMA), |p| p.parse_trait_ref()) @@ -2756,7 +2756,7 @@ impl parser { None) } - fn token_is_pound_or_doc_comment(++tok: token::token) -> bool { + fn token_is_pound_or_doc_comment(++tok: token::Token) -> bool { match tok { token::POUND | token::DOC_COMMENT(_) => true, _ => false @@ -2841,7 +2841,7 @@ impl parser { self.eat_keyword(~"static") } - fn parse_mod_items(term: token::token, + fn parse_mod_items(term: token::Token, +first_item_attrs: ~[attribute]) -> _mod { // Shouldn't be any view items since we've already parsed an item attr let {attrs_remaining, view_items, items: starting_items} = @@ -3222,7 +3222,7 @@ impl parser { } } - fn fn_expr_lookahead(tok: token::token) -> bool { + fn fn_expr_lookahead(tok: token::Token) -> bool { match tok { token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true, _ => false @@ -3608,7 +3608,7 @@ impl parser { return self.fatal(~"expected crate directive"); } - fn parse_crate_directives(term: token::token, + fn parse_crate_directives(term: token::Token, first_outer_attr: ~[attribute]) -> ~[@crate_directive] { diff --git a/src/libsyntax/parse/prec.rs b/src/libsyntax/parse/prec.rs index 668301db6201..3fd905cb8ece 100644 --- a/src/libsyntax/parse/prec.rs +++ b/src/libsyntax/parse/prec.rs @@ -3,7 +3,7 @@ export unop_prec; export token_to_binop; use token::*; -use token::token; +use token::Token; use ast::*; /// Unary operators have higher precedence than binary @@ -19,7 +19,7 @@ const as_prec: uint = 11u; * Maps a token to a record specifying the corresponding binary * operator and its precedence */ -fn token_to_binop(tok: token) -> Option { +fn token_to_binop(tok: Token) -> Option { match tok { BINOP(STAR) => Some(mul), BINOP(SLASH) => Some(div), diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index a7d439b8ce6d..5151fd1bac83 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -1,5 +1,5 @@ use util::interner; -use util::interner::interner; +use util::interner::Interner; use std::map::HashMap; #[auto_serialize] @@ -19,7 +19,7 @@ enum binop { #[auto_serialize] #[auto_deserialize] -enum token { +enum Token { /* Expression-operator symbols. */ EQ, LT, @@ -84,7 +84,7 @@ enum nonterminal { nt_stmt(@ast::stmt), nt_pat( @ast::pat), nt_expr(@ast::expr), - nt_ty( @ast::ty), + nt_ty( @ast::Ty), nt_ident(ast::ident, bool), nt_path(@ast::path), nt_tt( @ast::token_tree), //needs @ed to break a circularity @@ -106,7 +106,7 @@ fn binop_to_str(o: binop) -> ~str { } } -fn to_str(in: @ident_interner, t: token) -> ~str { +fn to_str(in: @ident_interner, t: Token) -> ~str { match t { EQ => ~"=", LT => ~"<", @@ -192,7 +192,7 @@ fn to_str(in: @ident_interner, t: token) -> ~str { } } -pure fn can_begin_expr(t: token) -> bool { +pure fn can_begin_expr(t: Token) -> bool { match t { LPAREN => true, LBRACE => true, @@ -223,7 +223,7 @@ pure fn can_begin_expr(t: token) -> bool { } /// what's the opposite delimiter? -fn flip_delimiter(t: token::token) -> token::token { +fn flip_delimiter(t: token::Token) -> token::Token { match t { token::LPAREN => token::RPAREN, token::LBRACE => token::RBRACE, @@ -237,7 +237,7 @@ fn flip_delimiter(t: token::token) -> token::token { -fn is_lit(t: token) -> bool { +fn is_lit(t: Token) -> bool { match t { LIT_INT(_, _) => true, LIT_UINT(_, _) => true, @@ -248,22 +248,22 @@ fn is_lit(t: token) -> bool { } } -pure fn is_ident(t: token) -> bool { +pure fn is_ident(t: Token) -> bool { match t { IDENT(_, _) => true, _ => false } } -pure fn is_ident_or_path(t: token) -> bool { +pure fn is_ident_or_path(t: Token) -> bool { match t { IDENT(_, _) | INTERPOLATED(nt_path(*)) => true, _ => false } } -pure fn is_plain_ident(t: token) -> bool { +pure fn is_plain_ident(t: Token) -> bool { match t { IDENT(_, false) => true, _ => false } } -pure fn is_bar(t: token) -> bool { +pure fn is_bar(t: Token) -> bool { match t { BINOP(OR) | OROR => true, _ => false } } @@ -314,7 +314,7 @@ mod special_idents { } struct ident_interner { - priv interner: util::interner::interner<@~str>, + priv interner: util::interner::Interner<@~str>, } impl ident_interner { @@ -457,8 +457,8 @@ impl binop : cmp::Eq { pure fn ne(other: &binop) -> bool { !self.eq(other) } } -impl token : cmp::Eq { - pure fn eq(other: &token) -> bool { +impl Token : cmp::Eq { + pure fn eq(other: &Token) -> bool { match self { EQ => { match (*other) { @@ -720,7 +720,7 @@ impl token : cmp::Eq { } } } - pure fn ne(other: &token) -> bool { !self.eq(other) } + pure fn ne(other: &Token) -> bool { !self.eq(other) } } // Local Variables: diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b98014f421bb..5e37f7e18ece 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1,5 +1,5 @@ use parse::{comments, lexer, token}; -use codemap::codemap; +use codemap::CodeMap; use pp::{break_offset, word, printer, space, zerobreak, hardbreak, breaks}; use pp::{consistent, inconsistent, eof}; use ast::{required, provided}; @@ -24,7 +24,7 @@ fn no_ann() -> pp_ann { type ps = @{s: pp::printer, - cm: Option, + cm: Option, intr: @token::ident_interner, comments: Option<~[comments::cmnt]>, literals: Option<~[comments::lit]>, @@ -45,7 +45,7 @@ fn end(s: ps) { fn rust_printer(writer: io::Writer, intr: @ident_interner) -> ps { return @{s: pp::mk_printer(writer, default_columns), - cm: None::, + cm: None::, intr: intr, comments: None::<~[comments::cmnt]>, literals: None::<~[comments::lit]>, @@ -63,7 +63,7 @@ const default_columns: uint = 78u; // Requires you to pass an input filename and reader so that // it can scan the input text for comments and literals to // copy forward. -fn print_crate(cm: codemap, intr: @ident_interner, +fn print_crate(cm: CodeMap, intr: @ident_interner, span_diagnostic: diagnostic::span_handler, crate: @ast::crate, filename: ~str, in: io::Reader, out: io::Writer, ann: pp_ann, is_expanded: bool) { @@ -91,7 +91,7 @@ fn print_crate_(s: ps, &&crate: @ast::crate) { eof(s.s); } -fn ty_to_str(ty: @ast::ty, intr: @ident_interner) -> ~str { +fn ty_to_str(ty: @ast::Ty, intr: @ident_interner) -> ~str { to_str(ty, print_type, intr) } @@ -348,11 +348,11 @@ fn print_region(s: ps, region: @ast::region, sep: ~str) { word(s.s, sep); } -fn print_type(s: ps, &&ty: @ast::ty) { +fn print_type(s: ps, &&ty: @ast::Ty) { print_type_ex(s, ty, false); } -fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) { +fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) { maybe_print_comment(s, ty.span.lo); ibox(s, 0u); match ty.node { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 5d991bb3551c..f564589cbe0c 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -12,14 +12,14 @@ type hash_interner = {map: HashMap, vect: DVec}; -fn mk() -> interner { +fn mk() -> Interner { let m = map::HashMap::(); let hi: hash_interner = {map: m, vect: DVec()}; - move ((move hi) as interner::) + move ((move hi) as Interner::) } -fn mk_prefill(init: ~[T]) -> interner { +fn mk_prefill(init: ~[T]) -> Interner { let rv = mk(); for init.each() |v| { rv.intern(*v); } return rv; @@ -27,14 +27,14 @@ fn mk_prefill(init: ~[T]) -> interner { /* when traits can extend traits, we should extend index to get [] */ -trait interner { +trait Interner { fn intern(T) -> uint; fn gensym(T) -> uint; pure fn get(uint) -> T; fn len() -> uint; } -impl hash_interner: interner { +impl hash_interner: Interner { fn intern(val: T) -> uint { match self.map.find(val) { Some(idx) => return idx, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index b402f9727dc2..32fcbdfc7589 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -55,7 +55,7 @@ type visitor = visit_decl: fn@(@decl, E, vt), visit_expr: fn@(@expr, E, vt), visit_expr_post: fn@(@expr, E, vt), - visit_ty: fn@(@ty, E, vt), + visit_ty: fn@(@Ty, E, vt), visit_ty_params: fn@(~[ty_param], E, vt), visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt), visit_ty_method: fn@(ty_method, E, vt), @@ -187,9 +187,9 @@ fn visit_enum_def(enum_definition: ast::enum_def, tps: ~[ast::ty_param], } } -fn skip_ty(_t: @ty, _e: E, _v: vt) {} +fn skip_ty(_t: @Ty, _e: E, _v: vt) {} -fn visit_ty(t: @ty, e: E, v: vt) { +fn visit_ty(t: @Ty, e: E, v: vt) { match t.node { ty_box(mt) | ty_uniq(mt) | ty_vec(mt) | ty_ptr(mt) | ty_rptr(_, mt) => { @@ -490,7 +490,7 @@ type simple_visitor = visit_decl: fn@(@decl), visit_expr: fn@(@expr), visit_expr_post: fn@(@expr), - visit_ty: fn@(@ty), + visit_ty: fn@(@Ty), visit_ty_params: fn@(~[ty_param]), visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id), visit_ty_method: fn@(ty_method), @@ -499,7 +499,7 @@ type simple_visitor = visit_struct_field: fn@(@struct_field), visit_struct_method: fn@(@method)}; -fn simple_ignore_ty(_t: @ty) {} +fn simple_ignore_ty(_t: @Ty) {} fn default_simple_visitor() -> simple_visitor { return @{visit_mod: fn@(_m: _mod, _sp: span, _id: node_id) { }, @@ -577,7 +577,7 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> { fn v_expr_post(f: fn@(@expr), ex: @expr, &&_e: (), _v: vt<()>) { f(ex); } - fn v_ty(f: fn@(@ty), ty: @ty, &&e: (), v: vt<()>) { + fn v_ty(f: fn@(@Ty), ty: @Ty, &&e: (), v: vt<()>) { f(ty); visit_ty(ty, e, v); } diff --git a/src/rustc/back/link.rs b/src/rustc/back/link.rs index 67edf6a32ba5..61fd68c193a6 100644 --- a/src/rustc/back/link.rs +++ b/src/rustc/back/link.rs @@ -1,6 +1,6 @@ use libc::{c_int, c_uint, c_char}; use driver::session; -use session::session; +use session::Session; use lib::llvm::llvm; use syntax::attr; use middle::ty; @@ -33,14 +33,14 @@ impl output_type : cmp::Eq { pure fn ne(other: &output_type) -> bool { !self.eq(other) } } -fn llvm_err(sess: session, msg: ~str) -> ! unsafe { +fn llvm_err(sess: Session, msg: ~str) -> ! unsafe { let cstr = llvm::LLVMRustGetLastError(); if cstr == ptr::null() { sess.fatal(msg); } else { sess.fatal(msg + ~": " + str::raw::from_c_str(cstr)); } } -fn WriteOutputFile(sess:session, +fn WriteOutputFile(sess: Session, PM: lib::llvm::PassManagerRef, M: ModuleRef, Triple: *c_char, // FIXME: When #2334 is fixed, change @@ -69,7 +69,7 @@ mod jit { env: *(), } - fn exec(sess: session, + fn exec(sess: Session, pm: PassManagerRef, m: ModuleRef, opt: c_int, @@ -131,7 +131,7 @@ mod write { return false; } - fn run_passes(sess: session, llmod: ModuleRef, output: &Path) { + fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) { let opts = sess.opts; if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } let mut pm = mk_pass_manager(); @@ -384,7 +384,7 @@ mod write { * */ -fn build_link_meta(sess: session, c: ast::crate, output: &Path, +fn build_link_meta(sess: Session, c: ast::crate, output: &Path, symbol_hasher: &hash::State) -> link_meta { type provided_metas = @@ -392,7 +392,7 @@ fn build_link_meta(sess: session, c: ast::crate, output: &Path, vers: Option<~str>, cmh_items: ~[@ast::meta_item]}; - fn provided_link_metas(sess: session, c: ast::crate) -> + fn provided_link_metas(sess: Session, c: ast::crate) -> provided_metas { let mut name: Option<~str> = None; let mut vers: Option<~str> = None; @@ -454,13 +454,13 @@ fn build_link_meta(sess: session, c: ast::crate, output: &Path, return truncated_hash_result(symbol_hasher); } - fn warn_missing(sess: session, name: ~str, default: ~str) { + fn warn_missing(sess: Session, name: ~str, default: ~str) { if !sess.building_library { return; } sess.warn(fmt!("missing crate link meta `%s`, using `%s` as default", name, default)); } - fn crate_meta_name(sess: session, _crate: ast::crate, + fn crate_meta_name(sess: Session, _crate: ast::crate, output: &Path, metas: provided_metas) -> ~str { return match metas.name { Some(v) => v, @@ -477,7 +477,7 @@ fn build_link_meta(sess: session, c: ast::crate, output: &Path, }; } - fn crate_meta_vers(sess: session, _crate: ast::crate, + fn crate_meta_vers(sess: Session, _crate: ast::crate, metas: provided_metas) -> ~str { return match metas.vers { Some(v) => v, @@ -569,7 +569,7 @@ fn sanitize(s: ~str) -> ~str { return result; } -fn mangle(sess: session, ss: path) -> ~str { +fn mangle(sess: Session, ss: path) -> ~str { // Follow C++ namespace-mangling style let mut n = ~"_ZN"; // Begin name-sequence. @@ -584,7 +584,7 @@ fn mangle(sess: session, ss: path) -> ~str { n } -fn exported_name(sess: session, path: path, hash: ~str, vers: ~str) -> ~str { +fn exported_name(sess: Session, path: path, hash: ~str, vers: ~str) -> ~str { return mangle(sess, vec::append_one( vec::append_one(path, path_name(sess.ident_of(hash))), @@ -623,7 +623,7 @@ fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: ~str) -> ~str { // If the user wants an exe generated we need to invoke // cc to link the object file with some libs -fn link_binary(sess: session, +fn link_binary(sess: Session, obj_filename: &Path, out_filename: &Path, lm: link_meta) { diff --git a/src/rustc/back/rpath.rs b/src/rustc/back/rpath.rs index 8aa7caefc7a5..8038d7bb6ddf 100644 --- a/src/rustc/back/rpath.rs +++ b/src/rustc/back/rpath.rs @@ -13,7 +13,7 @@ pure fn not_win32(os: session::os) -> bool { } } -fn get_rpath_flags(sess: session::session, out_filename: &Path) -> ~[~str] { +fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> ~[~str] { let os = sess.targ_cfg.os; // No rpath on windows @@ -35,7 +35,7 @@ fn get_rpath_flags(sess: session::session, out_filename: &Path) -> ~[~str] { rpaths_to_flags(rpaths) } -fn get_sysroot_absolute_rt_lib(sess: session::session) -> Path { +fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path { let r = filesearch::relative_target_lib_path(sess.opts.target_triple); sess.filesearch.sysroot().push_rel(&r).push(os::dll_filename("rustrt")) } diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index e389f3a4bdf7..5da8f5475ed1 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -1,6 +1,6 @@ // -*- rust -*- use metadata::{creader, cstore, filesearch}; -use session::{session, session_, OptLevel, No, Less, Default, Aggressive}; +use session::{Session, Session_, OptLevel, No, Less, Default, Aggressive}; use syntax::parse; use syntax::{ast, codemap}; use syntax::attr; @@ -32,7 +32,7 @@ fn source_name(input: input) -> ~str { } } -fn default_configuration(sess: session, argv0: ~str, input: input) -> +fn default_configuration(sess: Session, argv0: ~str, input: input) -> ast::crate_cfg { let libc = match sess.targ_cfg.os { session::os_win32 => ~"msvcrt.dll", @@ -70,7 +70,7 @@ fn append_configuration(cfg: ast::crate_cfg, name: ~str) -> ast::crate_cfg { } } -fn build_configuration(sess: session, argv0: ~str, input: input) -> +fn build_configuration(sess: Session, argv0: ~str, input: input) -> ast::crate_cfg { // Combine the configuration requested by the session (command line) with // some default and generated configuration items @@ -106,7 +106,7 @@ enum input { str_input(~str) } -fn parse_input(sess: session, cfg: ast::crate_cfg, input: input) +fn parse_input(sess: Session, cfg: ast::crate_cfg, input: input) -> @ast::crate { match input { file_input(file) => { @@ -145,7 +145,7 @@ impl compile_upto : cmp::Eq { pure fn ne(other: &compile_upto) -> bool { !self.eq(other) } } -fn compile_upto(sess: session, cfg: ast::crate_cfg, +fn compile_upto(sess: Session, cfg: ast::crate_cfg, input: input, upto: compile_upto, outputs: Option) -> {crate: @ast::crate, tcx: Option} { @@ -277,7 +277,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, return {crate: crate, tcx: Some(ty_cx)}; } -fn compile_input(sess: session, cfg: ast::crate_cfg, input: input, +fn compile_input(sess: Session, cfg: ast::crate_cfg, input: input, outdir: &Option, output: &Option) { let upto = if sess.opts.parse_only { cu_parse } @@ -287,7 +287,7 @@ fn compile_input(sess: session, cfg: ast::crate_cfg, input: input, compile_upto(sess, cfg, input, upto, Some(outputs)); } -fn pretty_print_input(sess: session, cfg: ast::crate_cfg, input: input, +fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: input, ppm: pp_mode) { fn ann_paren_for_expr(node: pprust::ann_node) { match node { @@ -571,7 +571,7 @@ fn build_session_options(binary: ~str, } fn build_session(sopts: @session::options, - demitter: diagnostic::emitter) -> session { + demitter: diagnostic::emitter) -> Session { let codemap = codemap::new_codemap(); let diagnostic_handler = diagnostic::mk_handler(Some(demitter)); @@ -581,11 +581,10 @@ fn build_session(sopts: @session::options, } fn build_session_(sopts: @session::options, - cm: codemap::codemap, + cm: codemap::CodeMap, demitter: diagnostic::emitter, span_diagnostic_handler: diagnostic::span_handler) - -> session { - + -> Session { let target_cfg = build_target_config(sopts, demitter); let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, cm); @@ -595,7 +594,7 @@ fn build_session_(sopts: @session::options, sopts.target_triple, sopts.addl_lib_search_paths); let lint_settings = lint::mk_lint_settings(); - session_(@{targ_cfg: target_cfg, + Session_(@{targ_cfg: target_cfg, opts: sopts, cstore: cstore, parse_sess: p_s, @@ -609,7 +608,7 @@ fn build_session_(sopts: @session::options, lint_settings: lint_settings}) } -fn parse_pretty(sess: session, &&name: ~str) -> pp_mode { +fn parse_pretty(sess: Session, &&name: ~str) -> pp_mode { match name { ~"normal" => ppm_normal, ~"expanded" => ppm_expanded, @@ -652,7 +651,7 @@ type output_filenames = @{out_filename:Path, obj_filename:Path}; fn build_output_filenames(input: input, odir: &Option, ofile: &Option, - sess: session) + sess: Session) -> output_filenames { let obj_path; let out_path; @@ -728,7 +727,7 @@ fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! { fail; } -fn list_metadata(sess: session, path: &Path, out: io::Writer) { +fn list_metadata(sess: Session, path: &Path, out: io::Writer) { metadata::loader::list_file_metadata( sess.parse_sess.interner, session::sess_os_to_meta_os(sess.targ_cfg.os), path, out); diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index 5833723ec101..59d4e0dfdb84 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -235,7 +235,7 @@ fn monitor(+f: fn~(diagnostic::emitter)) { // The 'diagnostics emitter'. Every error, warning, etc. should // go through this function. - let demitter = fn@(cmsp: Option<(codemap::codemap, codemap::span)>, + let demitter = fn@(cmsp: Option<(codemap::CodeMap, codemap::span)>, msg: &str, lvl: diagnostic::level) { if lvl == diagnostic::fatal { comm::send(ch, fatal); diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs index 550656c23df6..ed73bcb6d725 100644 --- a/src/rustc/driver/session.rs +++ b/src/rustc/driver/session.rs @@ -127,24 +127,24 @@ type options = type crate_metadata = {name: ~str, data: ~[u8]}; -type session_ = {targ_cfg: @config, +type Session_ = {targ_cfg: @config, opts: @options, - cstore: metadata::cstore::cstore, + cstore: metadata::cstore::CStore, parse_sess: parse_sess, - codemap: codemap::codemap, + codemap: codemap::CodeMap, // For a library crate, this is always none mut main_fn: Option<(node_id, codemap::span)>, span_diagnostic: diagnostic::span_handler, - filesearch: filesearch::filesearch, + filesearch: filesearch::FileSearch, mut building_library: bool, working_dir: Path, lint_settings: lint::lint_settings}; -enum session { - session_(@session_) +enum Session { + Session_(@Session_) } -impl session { +impl Session { fn span_fatal(sp: span, msg: ~str) -> ! { self.span_diagnostic.span_fatal(sp, msg) } @@ -270,7 +270,7 @@ fn basic_options() -> @options { } // Seems out of place, but it uses session, so I'm putting it here -fn expect(sess: session, opt: Option, msg: fn() -> ~str) -> T { +fn expect(sess: Session, opt: Option, msg: fn() -> ~str) -> T { diagnostic::expect(sess.diagnostic(), opt, msg) } diff --git a/src/rustc/front/core_inject.rs b/src/rustc/front/core_inject.rs index f198a2ca79dc..e9be56e7d480 100644 --- a/src/rustc/front/core_inject.rs +++ b/src/rustc/front/core_inject.rs @@ -1,4 +1,4 @@ -use driver::session::session; +use driver::session::Session; use syntax::codemap; use syntax::ast; use syntax::ast_util::*; @@ -6,7 +6,7 @@ use syntax::attr; export maybe_inject_libcore_ref; -fn maybe_inject_libcore_ref(sess: session, +fn maybe_inject_libcore_ref(sess: Session, crate: @ast::crate) -> @ast::crate { if use_core(crate) { inject_libcore_ref(sess, crate) @@ -19,7 +19,7 @@ fn use_core(crate: @ast::crate) -> bool { !attr::attrs_contains_name(crate.node.attrs, ~"no_core") } -fn inject_libcore_ref(sess: session, +fn inject_libcore_ref(sess: Session, crate: @ast::crate) -> @ast::crate { fn spanned(x: T) -> @ast::spanned { diff --git a/src/rustc/front/intrinsic_inject.rs b/src/rustc/front/intrinsic_inject.rs index 8fd885e8f8b5..ac74bac3f2f1 100644 --- a/src/rustc/front/intrinsic_inject.rs +++ b/src/rustc/front/intrinsic_inject.rs @@ -1,10 +1,10 @@ -use driver::session::session; +use driver::session::Session; use syntax::parse; use syntax::ast; export inject_intrinsic; -fn inject_intrinsic(sess: session, +fn inject_intrinsic(sess: Session, crate: @ast::crate) -> @ast::crate { let intrinsic_module = @include_str!("intrinsic.rs"); diff --git a/src/rustc/front/test.rs b/src/rustc/front/test.rs index 1a6cc6dd895e..f0c9de4f2a24 100644 --- a/src/rustc/front/test.rs +++ b/src/rustc/front/test.rs @@ -7,7 +7,7 @@ use syntax::fold; use syntax::print::pprust; use syntax::codemap::span; use driver::session; -use session::session; +use session::Session; use syntax::attr; use dvec::DVec; @@ -19,14 +19,14 @@ type test = {span: span, path: ~[ast::ident], ignore: bool, should_fail: bool}; type test_ctxt = - @{sess: session::session, + @{sess: session::Session, crate: @ast::crate, mut path: ~[ast::ident], testfns: DVec}; // Traverse the crate, collecting all the test functions, eliding any // existing main functions, and synthesizing a main test harness -fn modify_for_testing(sess: session::session, +fn modify_for_testing(sess: session::Session, crate: @ast::crate) -> @ast::crate { if sess.opts.test { @@ -36,7 +36,7 @@ fn modify_for_testing(sess: session::session, } } -fn generate_test_harness(sess: session::session, +fn generate_test_harness(sess: session::Session, crate: @ast::crate) -> @ast::crate { let cx: test_ctxt = @{sess: sess, @@ -261,13 +261,13 @@ fn mk_path(cx: test_ctxt, path: ~[ast::ident]) -> ~[ast::ident] { else { vec::append(~[cx.sess.ident_of(~"std")], path) } } -// The ast::ty of ~[std::test::test_desc] -fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::ty { +// The ast::Ty of ~[std::test::test_desc] +fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty { let test_desc_ty_path = path_node(mk_path(cx, ~[cx.sess.ident_of(~"test"), cx.sess.ident_of(~"TestDesc")])); - let test_desc_ty: ast::ty = + let test_desc_ty: ast::Ty = {id: cx.sess.next_node_id(), node: ast::ty_path(test_desc_ty_path, cx.sess.next_node_id()), span: dummy_sp()}; diff --git a/src/rustc/metadata/creader.rs b/src/rustc/metadata/creader.rs index 3ed56a1953e6..3080426e5319 100644 --- a/src/rustc/metadata/creader.rs +++ b/src/rustc/metadata/creader.rs @@ -7,7 +7,7 @@ use syntax::visit; use syntax::codemap::span; use std::map::HashMap; use syntax::print::pprust; -use filesearch::filesearch; +use filesearch::FileSearch; use common::*; use dvec::DVec; use syntax::parse::token::ident_interner; @@ -17,7 +17,7 @@ export read_crates; // Traverses an AST, reading all the information about use'd crates and extern // libraries necessary for later resolving, typechecking, linking, etc. fn read_crates(diag: span_handler, crate: ast::crate, - cstore: cstore::cstore, filesearch: filesearch, + cstore: cstore::CStore, filesearch: FileSearch, os: loader::os, static: bool, intr: @ident_interner) { let e = @{diag: diag, filesearch: filesearch, @@ -88,8 +88,8 @@ fn warn_if_multiple_versions(e: env, diag: span_handler, } type env = @{diag: span_handler, - filesearch: filesearch, - cstore: cstore::cstore, + filesearch: FileSearch, + cstore: cstore::CStore, os: loader::os, static: bool, crate_cache: DVec, diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index ea6bd499a3b5..d9fccb16de02 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -39,18 +39,18 @@ struct ProvidedTraitMethodInfo { def_id: ast::def_id } -fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> ~str { +fn get_symbol(cstore: cstore::CStore, def: ast::def_id) -> ~str { let cdata = cstore::get_crate_data(cstore, def.crate).data; return decoder::get_symbol(cdata, def.node); } -fn get_type_param_count(cstore: cstore::cstore, def: ast::def_id) -> uint { +fn get_type_param_count(cstore: cstore::CStore, def: ast::def_id) -> uint { let cdata = cstore::get_crate_data(cstore, def.crate).data; return decoder::get_type_param_count(cdata, def.node); } /// Iterates over all the paths in the given crate. -fn each_path(cstore: cstore::cstore, cnum: ast::crate_num, +fn each_path(cstore: cstore::CStore, cnum: ast::crate_num, f: fn(decoder::path_entry) -> bool) { let crate_data = cstore::get_crate_data(cstore, cnum); decoder::each_path(cstore.intr, crate_data, f); @@ -91,7 +91,7 @@ fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id) return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx) } -fn get_impls_for_mod(cstore: cstore::cstore, def: ast::def_id, +fn get_impls_for_mod(cstore: cstore::CStore, def: ast::def_id, name: Option) -> @~[@decoder::_impl] { let cdata = cstore::get_crate_data(cstore, def.crate); @@ -113,14 +113,14 @@ fn get_provided_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx) } -fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id) +fn get_method_names_if_trait(cstore: cstore::CStore, def: ast::def_id) -> Option<@DVec<(ast::ident, ast::self_ty_)>> { let cdata = cstore::get_crate_data(cstore, def.crate); return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node); } -fn get_item_attrs(cstore: cstore::cstore, +fn get_item_attrs(cstore: cstore::CStore, def_id: ast::def_id, f: fn(~[@ast::meta_item])) { @@ -140,7 +140,7 @@ fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty { decoder::get_type(cdata, def.node, tcx) } -fn get_region_param(cstore: metadata::cstore::cstore, +fn get_region_param(cstore: metadata::cstore::CStore, def: ast::def_id) -> Option { let cdata = cstore::get_crate_data(cstore, def.crate); return decoder::get_region_param(cdata, def.node); @@ -177,7 +177,7 @@ fn get_impl_traits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] { decoder::get_impl_traits(cdata, def.node, tcx) } -fn get_impl_method(cstore: cstore::cstore, +fn get_impl_method(cstore: cstore::CStore, def: ast::def_id, mname: ast::ident) -> ast::def_id { let cdata = cstore::get_crate_data(cstore, def.crate); @@ -188,7 +188,7 @@ fn get_impl_method(cstore: cstore::cstore, for their methods (so that get_trait_methods can be reused to get class methods), classes require a slightly different version of get_impl_method. Sigh. */ -fn get_class_method(cstore: cstore::cstore, +fn get_class_method(cstore: cstore::CStore, def: ast::def_id, mname: ast::ident) -> ast::def_id { let cdata = cstore::get_crate_data(cstore, def.crate); @@ -196,7 +196,7 @@ fn get_class_method(cstore: cstore::cstore, } /* If def names a class with a dtor, return it. Otherwise, return none. */ -fn class_dtor(cstore: cstore::cstore, def: ast::def_id) +fn class_dtor(cstore: cstore::CStore, def: ast::def_id) -> Option { let cdata = cstore::get_crate_data(cstore, def.crate); decoder::class_dtor(cdata, def.node) diff --git a/src/rustc/metadata/cstore.rs b/src/rustc/metadata/cstore.rs index 483f7ea06a99..4bbca3a06050 100644 --- a/src/rustc/metadata/cstore.rs +++ b/src/rustc/metadata/cstore.rs @@ -6,7 +6,7 @@ use std::map::HashMap; use syntax::{ast, attr}; use syntax::parse::token::ident_interner; -export cstore; +export CStore; export cnum_map; export crate_metadata; export mk_cstore; @@ -49,7 +49,7 @@ type crate_metadata = @{name: ~str, // other modules to access the cstore's private data. This could also be // achieved with an obj, but at the expense of a vtable. Not sure if this is a // good pattern or not. -enum cstore { private(cstore_private), } +enum CStore { private(cstore_private), } type cstore_private = @{metas: map::HashMap, @@ -64,11 +64,11 @@ type cstore_private = type use_crate_map = map::HashMap; // Internal method to retrieve the data from the cstore -pure fn p(cstore: cstore) -> cstore_private { +pure fn p(cstore: CStore) -> cstore_private { match cstore { private(p) => p } } -fn mk_cstore(intr: @ident_interner) -> cstore { +fn mk_cstore(intr: @ident_interner) -> CStore { let meta_cache = map::HashMap(); let crate_map = map::HashMap(); let mod_path_map = HashMap(); @@ -81,21 +81,21 @@ fn mk_cstore(intr: @ident_interner) -> cstore { intr: intr}); } -fn get_crate_data(cstore: cstore, cnum: ast::crate_num) -> crate_metadata { +fn get_crate_data(cstore: CStore, cnum: ast::crate_num) -> crate_metadata { return p(cstore).metas.get(cnum); } -fn get_crate_hash(cstore: cstore, cnum: ast::crate_num) -> ~str { +fn get_crate_hash(cstore: CStore, cnum: ast::crate_num) -> ~str { let cdata = get_crate_data(cstore, cnum); return decoder::get_crate_hash(cdata.data); } -fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> ~str { +fn get_crate_vers(cstore: CStore, cnum: ast::crate_num) -> ~str { let cdata = get_crate_data(cstore, cnum); return decoder::get_crate_vers(cdata.data); } -fn set_crate_data(cstore: cstore, cnum: ast::crate_num, +fn set_crate_data(cstore: CStore, cnum: ast::crate_num, data: crate_metadata) { p(cstore).metas.insert(cnum, data); for vec::each(decoder::get_crate_module_paths(cstore.intr, data)) |dp| { @@ -105,25 +105,25 @@ fn set_crate_data(cstore: cstore, cnum: ast::crate_num, } } -fn have_crate_data(cstore: cstore, cnum: ast::crate_num) -> bool { +fn have_crate_data(cstore: CStore, cnum: ast::crate_num) -> bool { return p(cstore).metas.contains_key(cnum); } -fn iter_crate_data(cstore: cstore, i: fn(ast::crate_num, crate_metadata)) { +fn iter_crate_data(cstore: CStore, i: fn(ast::crate_num, crate_metadata)) { for p(cstore).metas.each |k,v| { i(k, v);}; } -fn add_used_crate_file(cstore: cstore, lib: &Path) { +fn add_used_crate_file(cstore: CStore, lib: &Path) { if !vec::contains(p(cstore).used_crate_files, lib) { p(cstore).used_crate_files.push(copy *lib); } } -fn get_used_crate_files(cstore: cstore) -> ~[Path] { +fn get_used_crate_files(cstore: CStore) -> ~[Path] { return p(cstore).used_crate_files; } -fn add_used_library(cstore: cstore, lib: ~str) -> bool { +fn add_used_library(cstore: CStore, lib: ~str) -> bool { assert lib != ~""; if vec::contains(p(cstore).used_libraries, &lib) { return false; } @@ -131,31 +131,31 @@ fn add_used_library(cstore: cstore, lib: ~str) -> bool { return true; } -fn get_used_libraries(cstore: cstore) -> ~[~str] { +fn get_used_libraries(cstore: CStore) -> ~[~str] { return p(cstore).used_libraries; } -fn add_used_link_args(cstore: cstore, args: ~str) { +fn add_used_link_args(cstore: CStore, args: ~str) { p(cstore).used_link_args.push_all(str::split_char(args, ' ')); } -fn get_used_link_args(cstore: cstore) -> ~[~str] { +fn get_used_link_args(cstore: CStore) -> ~[~str] { return p(cstore).used_link_args; } -fn add_use_stmt_cnum(cstore: cstore, use_id: ast::node_id, +fn add_use_stmt_cnum(cstore: CStore, use_id: ast::node_id, cnum: ast::crate_num) { p(cstore).use_crate_map.insert(use_id, cnum); } -fn find_use_stmt_cnum(cstore: cstore, +fn find_use_stmt_cnum(cstore: CStore, use_id: ast::node_id) -> Option { p(cstore).use_crate_map.find(use_id) } // returns hashes of crates directly used by this crate. Hashes are // sorted by crate name. -fn get_dep_hashes(cstore: cstore) -> ~[~str] { +fn get_dep_hashes(cstore: CStore) -> ~[~str] { type crate_hash = {name: ~str, hash: ~str}; let mut result = ~[]; @@ -175,7 +175,7 @@ fn get_dep_hashes(cstore: cstore) -> ~[~str] { return vec::map(sorted, mapper); } -fn get_path(cstore: cstore, d: ast::def_id) -> ~[~str] { +fn get_path(cstore: CStore, d: ast::def_id) -> ~[~str] { option::map_default(&p(cstore).mod_path_map.find(d), ~[], |ds| str::split_str(**ds, ~"::")) } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 652af81659a0..0b25f0670b42 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -52,7 +52,7 @@ type encode_parms = { item_symbols: HashMap, discrim_symbols: HashMap, link_meta: link_meta, - cstore: cstore::cstore, + cstore: cstore::CStore, encode_inlined_item: encode_inlined_item }; @@ -77,7 +77,7 @@ enum encode_ctxt = { item_symbols: HashMap, discrim_symbols: HashMap, link_meta: link_meta, - cstore: cstore::cstore, + cstore: cstore::CStore, encode_inlined_item: encode_inlined_item, type_abbrevs: abbrev_map }; @@ -1035,9 +1035,9 @@ fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] { } fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::Serializer, - cstore: cstore::cstore) { + cstore: cstore::CStore) { - fn get_ordered_deps(ecx: @encode_ctxt, cstore: cstore::cstore) + fn get_ordered_deps(ecx: @encode_ctxt, cstore: cstore::CStore) -> ~[decoder::crate_dep] { type hashkv = @{key: crate_num, val: cstore::crate_metadata}; diff --git a/src/rustc/metadata/filesearch.rs b/src/rustc/metadata/filesearch.rs index 63370b093210..b2d20ce56e83 100644 --- a/src/rustc/metadata/filesearch.rs +++ b/src/rustc/metadata/filesearch.rs @@ -3,7 +3,7 @@ // probably just be folded into cstore. use result::Result; -export filesearch; +export FileSearch; export mk_filesearch; export pick; export pick_file; @@ -21,7 +21,7 @@ fn pick_file(file: Path, path: &Path) -> Option { else { option::None } } -trait filesearch { +trait FileSearch { fn sysroot() -> Path; fn lib_search_paths() -> ~[Path]; fn get_target_lib_path() -> Path; @@ -30,11 +30,11 @@ trait filesearch { fn mk_filesearch(maybe_sysroot: Option, target_triple: &str, - addl_lib_search_paths: ~[Path]) -> filesearch { + addl_lib_search_paths: ~[Path]) -> FileSearch { type filesearch_impl = {sysroot: Path, addl_lib_search_paths: ~[Path], target_triple: ~str}; - impl filesearch_impl: filesearch { + impl filesearch_impl: FileSearch { fn sysroot() -> Path { self.sysroot } fn lib_search_paths() -> ~[Path] { let mut paths = self.addl_lib_search_paths; @@ -64,10 +64,10 @@ fn mk_filesearch(maybe_sysroot: Option, debug!("using sysroot = %s", sysroot.to_str()); {sysroot: sysroot, addl_lib_search_paths: addl_lib_search_paths, - target_triple: str::from_slice(target_triple)} as filesearch + target_triple: str::from_slice(target_triple)} as FileSearch } -fn search(filesearch: filesearch, pick: pick) -> Option { +fn search(filesearch: FileSearch, pick: pick) -> Option { let mut rslt = None; for filesearch.lib_search_paths().each |lib_search_path| { debug!("searching %s", lib_search_path.to_str()); diff --git a/src/rustc/metadata/loader.rs b/src/rustc/metadata/loader.rs index 0a8354be71f7..61b8bcf9067b 100644 --- a/src/rustc/metadata/loader.rs +++ b/src/rustc/metadata/loader.rs @@ -5,7 +5,7 @@ use syntax::{ast, attr}; use syntax::print::pprust; use syntax::codemap::span; use lib::llvm::{False, llvm, mk_object_file, mk_section_iter}; -use filesearch::filesearch; +use filesearch::FileSearch; use io::WriterUtil; use syntax::parse::token::ident_interner; @@ -28,7 +28,7 @@ enum os { type ctxt = { diag: span_handler, - filesearch: filesearch, + filesearch: FileSearch, span: span, ident: ast::ident, metas: ~[@ast::meta_item], @@ -66,7 +66,7 @@ fn libname(cx: ctxt) -> {prefix: ~str, suffix: ~str} { fn find_library_crate_aux(cx: ctxt, nn: {prefix: ~str, suffix: ~str}, - filesearch: filesearch::filesearch) -> + filesearch: filesearch::FileSearch) -> Option<{ident: ~str, data: @~[u8]}> { let crate_name = crate_name_from_metas(cx.metas); let prefix: ~str = nn.prefix + crate_name + ~"-"; diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs index 1375ff2d0be0..14aef6db1adb 100644 --- a/src/rustc/metadata/tydecode.rs +++ b/src/rustc/metadata/tydecode.rs @@ -162,7 +162,7 @@ fn parse_bound_region(st: @pstate) -> ty::bound_region { } } -fn parse_region(st: @pstate) -> ty::region { +fn parse_region(st: @pstate) -> ty::Region { match next(st) { 'b' => { ty::re_bound(parse_bound_region(st)) diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index 69689b16e154..941dd35bdf0b 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -125,7 +125,7 @@ fn enc_substs(w: io::Writer, cx: @ctxt, substs: ty::substs) { w.write_char(']'); } -fn enc_region(w: io::Writer, cx: @ctxt, r: ty::region) { +fn enc_region(w: io::Writer, cx: @ctxt, r: ty::Region) { match r { ty::re_bound(br) => { w.write_char('b'); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index d1f766dd8672..b47e6d3b151c 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -19,7 +19,7 @@ use middle::{ty, typeck}; use middle::typeck::{method_origin, method_map_entry, vtable_res, vtable_origin}; -use driver::session::session; +use driver::session::Session; use middle::freevars::freevar_entry; use c = metadata::common; use e = metadata::encoder; @@ -136,7 +136,7 @@ fn decode_inlined_item(cdata: cstore::crate_metadata, // ______________________________________________________________________ // Enumerating the IDs which appear in an AST -fn reserve_id_range(sess: session, +fn reserve_id_range(sess: Session, from_id_range: ast_util::id_range) -> ast_util::id_range { // Handle the case of an empty range: if ast_util::empty(from_id_range) { return from_id_range; } @@ -379,8 +379,8 @@ impl ty::AutoRef: tr { } } -impl ty::region: tr { - fn tr(xcx: extended_decode_ctxt) -> ty::region { +impl ty::Region: tr { + fn tr(xcx: extended_decode_ctxt) -> ty::Region { match self { ty::re_bound(br) => ty::re_bound(br.tr(xcx)), ty::re_free(id, br) => ty::re_free(xcx.tr_id(id), br.tr(xcx)), diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index 02fd2998f4db..db0e092ed83e 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -229,7 +229,6 @@ use result::{Result, Ok, Err}; use syntax::print::pprust; use util::common::indenter; use ty::to_str; -use driver::session::session; use dvec::DVec; use mem_categorization::*; @@ -319,8 +318,8 @@ enum bckerr_code { err_mut_variant, err_root_not_permitted, err_mutbl(ast::mutability), - err_out_of_root_scope(ty::region, ty::region), // superscope, subscope - err_out_of_scope(ty::region, ty::region) // superscope, subscope + err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope + err_out_of_scope(ty::Region, ty::Region) // superscope, subscope } impl bckerr_code : cmp::Eq { @@ -436,7 +435,7 @@ fn root_map() -> root_map { // Misc impl borrowck_ctxt { - fn is_subregion_of(r_sub: ty::region, r_sup: ty::region) -> bool { + fn is_subregion_of(r_sub: ty::Region, r_sup: ty::Region) -> bool { region::is_subregion_of(self.tcx.region_map, r_sub, r_sup) } diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index e8d11fd1708f..e0eb5519d4da 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -260,7 +260,7 @@ impl gather_loan_ctxt { fn guarantee_valid(&self, cmt: cmt, req_mutbl: ast::mutability, - scope_r: ty::region) { + scope_r: ty::Region) { self.bccx.guaranteed_paths += 1; @@ -390,7 +390,7 @@ impl gather_loan_ctxt { fn add_loans(&self, cmt: cmt, req_mutbl: ast::mutability, - scope_r: ty::region, + scope_r: ty::Region, +loans: ~[Loan]) { if loans.len() == 0 { return; diff --git a/src/rustc/middle/borrowck/loan.rs b/src/rustc/middle/borrowck/loan.rs index 5d3ccc392139..7f4f857dae83 100644 --- a/src/rustc/middle/borrowck/loan.rs +++ b/src/rustc/middle/borrowck/loan.rs @@ -7,7 +7,7 @@ use result::{Result, Ok, Err}; impl borrowck_ctxt { fn loan(cmt: cmt, - scope_region: ty::region, + scope_region: ty::Region, mutbl: ast::mutability) -> bckres<~[Loan]> { let lc = LoanContext { bccx: self, @@ -28,7 +28,7 @@ struct LoanContext { bccx: borrowck_ctxt, // the region scope for which we must preserve the memory - scope_region: ty::region, + scope_region: ty::Region, // accumulated list of loans that will be required mut loans: ~[Loan] @@ -39,7 +39,7 @@ impl LoanContext { fn issue_loan(&self, cmt: cmt, - scope_ub: ty::region, + scope_ub: ty::Region, req_mutbl: ast::mutability) -> bckres<()> { if self.bccx.is_subregion_of(self.scope_region, scope_ub) { match req_mutbl { diff --git a/src/rustc/middle/borrowck/preserve.rs b/src/rustc/middle/borrowck/preserve.rs index 7e1d47eed694..556ea7867cfc 100644 --- a/src/rustc/middle/borrowck/preserve.rs +++ b/src/rustc/middle/borrowck/preserve.rs @@ -23,7 +23,7 @@ impl preserve_condition { impl borrowck_ctxt { fn preserve(cmt: cmt, - scope_region: ty::region, + scope_region: ty::Region, item_ub: ast::node_id, root_ub: ast::node_id) -> bckres { @@ -41,7 +41,7 @@ enum preserve_ctxt = { bccx: borrowck_ctxt, // the region scope for which we must preserve the memory - scope_region: ty::region, + scope_region: ty::Region, // the scope for the body of the enclosing fn/method item item_ub: ast::node_id, @@ -277,7 +277,7 @@ priv impl &preserve_ctxt { /// Checks that the scope for which the value must be preserved /// is a subscope of `scope_ub`; if so, success. fn compare_scope(cmt: cmt, - scope_ub: ty::region) -> bckres { + scope_ub: ty::Region) -> bckres { if self.bccx.is_subregion_of(self.scope_region, scope_ub) { Ok(pc_ok) } else { diff --git a/src/rustc/middle/capture.rs b/src/rustc/middle/capture.rs index 618d43e121a3..563ea8f84be7 100644 --- a/src/rustc/middle/capture.rs +++ b/src/rustc/middle/capture.rs @@ -1,5 +1,4 @@ use syntax::{ast, ast_util}; -use driver::session::session; use syntax::codemap::span; use std::map; use std::map::HashMap; diff --git a/src/rustc/middle/check_alt.rs b/src/rustc/middle/check_alt.rs index aab470f6907d..fc040ecc4cd3 100644 --- a/src/rustc/middle/check_alt.rs +++ b/src/rustc/middle/check_alt.rs @@ -7,7 +7,6 @@ use syntax::print::pprust::pat_to_str; use util::ppaux::ty_to_str; use pat_util::*; use syntax::visit; -use driver::session::session; use middle::ty; use middle::ty::*; use std::map::HashMap; diff --git a/src/rustc/middle/check_const.rs b/src/rustc/middle/check_const.rs index bd3abe201349..bdc042fb764e 100644 --- a/src/rustc/middle/check_const.rs +++ b/src/rustc/middle/check_const.rs @@ -1,10 +1,10 @@ use syntax::ast::*; use syntax::{visit, ast_util, ast_map}; -use driver::session::session; +use driver::session::Session; use std::map::HashMap; use dvec::DVec; -fn check_crate(sess: session, crate: @crate, ast_map: ast_map::map, +fn check_crate(sess: Session, crate: @crate, ast_map: ast_map::map, def_map: resolve::DefMap, method_map: typeck::method_map, tcx: ty::ctxt) { visit::visit_crate(*crate, false, visit::mk_vt(@{ @@ -17,7 +17,7 @@ fn check_crate(sess: session, crate: @crate, ast_map: ast_map::map, sess.abort_if_errors(); } -fn check_item(sess: session, ast_map: ast_map::map, +fn check_item(sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, it: @item, &&_is_const: bool, v: visit::vt) { match it.node { @@ -55,7 +55,7 @@ fn check_pat(p: @pat, &&_is_const: bool, v: visit::vt) { } } -fn check_expr(sess: session, def_map: resolve::DefMap, +fn check_expr(sess: Session, def_map: resolve::DefMap, method_map: typeck::method_map, tcx: ty::ctxt, e: @expr, &&is_const: bool, v: visit::vt) { if is_const { @@ -142,12 +142,12 @@ fn check_expr(sess: session, def_map: resolve::DefMap, // Make sure a const item doesn't recursively refer to itself // FIXME: Should use the dependency graph when it's available (#1356) -fn check_item_recursion(sess: session, ast_map: ast_map::map, +fn check_item_recursion(sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, it: @item) { type env = { root_it: @item, - sess: session, + sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, idstack: @DVec, diff --git a/src/rustc/middle/check_loop.rs b/src/rustc/middle/check_loop.rs index 3cd26f3039b4..3fa7f34fb33e 100644 --- a/src/rustc/middle/check_loop.rs +++ b/src/rustc/middle/check_loop.rs @@ -1,6 +1,5 @@ use syntax::ast::*; use syntax::visit; -use driver::session::session; type ctx = {in_loop: bool, can_ret: bool}; diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index 36a05d665061..e4dc9e8330e8 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -1,8 +1,7 @@ use syntax::{visit, ast_util}; use syntax::ast::*; use syntax::codemap::span; -use ty::{kind, kind_copyable, kind_noncopyable, kind_const}; -use driver::session::session; +use middle::ty::{Kind, kind_copyable, kind_noncopyable, kind_const}; use std::map::HashMap; use util::ppaux::{ty_to_str, tys_to_str}; use syntax::print::pprust::expr_to_str; @@ -40,7 +39,7 @@ use lint::{non_implicitly_copyable_typarams,implicit_copies}; const try_adding: &str = "Try adding a move"; -fn kind_to_str(k: kind) -> ~str { +fn kind_to_str(k: Kind) -> ~str { let mut kinds = ~[]; if ty::kind_lteq(kind_const(), k) { @@ -387,7 +386,7 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt) { visit::visit_stmt(stmt, cx, v); } -fn check_ty(aty: @ty, cx: ctx, v: visit::vt) { +fn check_ty(aty: @Ty, cx: ctx, v: visit::vt) { match aty.node { ty_path(_, id) => { do option::iter(&cx.tcx.node_type_substs.find(id)) |ts| { diff --git a/src/rustc/middle/lang_items.rs b/src/rustc/middle/lang_items.rs index 7cb2c9eb9cf1..383fe2db3231 100644 --- a/src/rustc/middle/lang_items.rs +++ b/src/rustc/middle/lang_items.rs @@ -9,7 +9,7 @@ // // * Functions called by the compiler itself. -use driver::session::session; +use driver::session::Session; use metadata::csearch::{each_path, get_item_attrs}; use metadata::cstore::{iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; @@ -50,7 +50,7 @@ struct LanguageItems { mut log_type_fn: Option } -mod LanguageItems { +mod language_items { #[legacy_exports]; fn make() -> LanguageItems { LanguageItems { @@ -83,7 +83,7 @@ mod LanguageItems { } } -fn LanguageItemCollector(crate: @crate, session: session, +fn LanguageItemCollector(crate: @crate, session: Session, items: &r/LanguageItems) -> LanguageItemCollector/&r { @@ -127,7 +127,7 @@ struct LanguageItemCollector { items: &LanguageItems, crate: @crate, - session: session, + session: Session, item_refs: HashMap<~str,&mut Option>, } @@ -239,8 +239,8 @@ impl LanguageItemCollector { } } -fn collect_language_items(crate: @crate, session: session) -> LanguageItems { - let items = LanguageItems::make(); +fn collect_language_items(crate: @crate, session: Session) -> LanguageItems { + let items = language_items::make(); let collector = LanguageItemCollector(crate, session, &items); collector.collect(); copy items diff --git a/src/rustc/middle/lint.rs b/src/rustc/middle/lint.rs index 0f31f2056a14..0768a0925224 100644 --- a/src/rustc/middle/lint.rs +++ b/src/rustc/middle/lint.rs @@ -1,5 +1,5 @@ use driver::session; -use driver::session::session; +use driver::session::Session; use middle::ty; use syntax::{ast, ast_util, visit}; use syntax::attr; @@ -244,7 +244,7 @@ fn clone_lint_modes(modes: lint_modes) -> lint_modes { type ctxt_ = {dict: lint_dict, curr: lint_modes, is_default: bool, - sess: session}; + sess: Session}; enum ctxt { ctxt_(ctxt_) @@ -355,7 +355,7 @@ fn build_settings_item(i: @ast::item, &&cx: ctxt, v: visit::vt) { } } -fn build_settings_crate(sess: session::session, crate: @ast::crate) { +fn build_settings_crate(sess: session::Session, crate: @ast::crate) { let cx = ctxt_({dict: get_lint_dict(), curr: std::smallintmap::mk(), diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index a0a422bc027b..89d5c842a9f6 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -99,7 +99,6 @@ use syntax::print::pprust::{expr_to_str}; use visit::vt; use syntax::codemap::span; use syntax::ast::*; -use driver::session::session; use io::WriterUtil; use capture::{cap_move, cap_drop, cap_copy, cap_ref}; diff --git a/src/rustc/middle/mem_categorization.rs b/src/rustc/middle/mem_categorization.rs index dc5874ea2cfa..a61cb28c16b1 100644 --- a/src/rustc/middle/mem_categorization.rs +++ b/src/rustc/middle/mem_categorization.rs @@ -122,7 +122,7 @@ impl categorization : cmp::Eq { enum ptr_kind { uniq_ptr, gc_ptr, - region_ptr(ty::region), + region_ptr(ty::Region), unsafe_ptr } @@ -993,7 +993,7 @@ impl &mem_categorization_ctxt { } } - fn region_to_str(r: ty::region) -> ~str { + fn region_to_str(r: ty::Region) -> ~str { region_to_str(self.tcx, r) } } diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index eb0bf8796f07..5c70cd3e2795 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -7,7 +7,7 @@ region parameterized. */ -use driver::session::session; +use driver::session::Session; use middle::ty; use syntax::{ast, visit}; use syntax::codemap::span; @@ -41,7 +41,7 @@ Encodes the bounding lifetime for a given AST node: type region_map = HashMap; struct ctxt { - sess: session, + sess: Session, def_map: resolve::DefMap, // Generated maps: @@ -108,8 +108,8 @@ fn scope_contains(region_map: region_map, superscope: ast::node_id, /// intended to run *after inference* and sadly the logic is somewhat /// duplicated with the code in infer.rs. fn is_subregion_of(region_map: region_map, - sub_region: ty::region, - super_region: ty::region) -> bool { + sub_region: ty::Region, + super_region: ty::Region) -> bool { sub_region == super_region || match (sub_region, super_region) { (_, ty::re_static) => { @@ -328,7 +328,7 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, visit::visit_fn(fk, decl, body, sp, id, fn_cx, visitor); } -fn resolve_crate(sess: session, def_map: resolve::DefMap, +fn resolve_crate(sess: Session, def_map: resolve::DefMap, crate: @ast::crate) -> region_map { let cx: ctxt = ctxt {sess: sess, def_map: def_map, @@ -382,7 +382,7 @@ impl region_dep : cmp::Eq { } type determine_rp_ctxt_ = { - sess: session, + sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, region_paramd_items: region_paramd_items, @@ -599,7 +599,7 @@ fn determine_rp_in_ty_method(ty_m: ast::ty_method, } } -fn determine_rp_in_ty(ty: @ast::ty, +fn determine_rp_in_ty(ty: @ast::Ty, &&cx: determine_rp_ctxt, visitor: visit::vt) { @@ -755,7 +755,7 @@ fn determine_rp_in_struct_field(cm: @ast::struct_field, } } -fn determine_rp_in_crate(sess: session, +fn determine_rp_in_crate(sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, crate: @ast::crate) -> region_paramd_items { diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 4f170fd050be..81ea6daf1958 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -1,4 +1,4 @@ -use driver::session::session; +use driver::session::Session; use metadata::csearch::{each_path, get_method_names_if_trait}; use metadata::cstore::find_use_stmt_cnum; use metadata::decoder::{def_like, dl_def, dl_field, dl_impl}; @@ -35,7 +35,7 @@ use syntax::ast::{pat_box, pat_lit, pat_range, pat_rec, pat_struct}; use syntax::ast::{pat_tup, pat_uniq, pat_wild, private, provided, public}; use syntax::ast::{required, rem, self_ty_, shl, shr, stmt_decl}; use syntax::ast::{struct_field, struct_variant_kind, sty_static, subtract}; -use syntax::ast::{trait_ref, tuple_variant_kind, ty, ty_bool, ty_char}; +use syntax::ast::{trait_ref, tuple_variant_kind, Ty, ty_bool, ty_char}; use syntax::ast::{ty_f, ty_f32, ty_f64, ty_float, ty_i, ty_i16, ty_i32}; use syntax::ast::{ty_i64, ty_i8, ty_int, ty_param, ty_path, ty_str, ty_u}; use syntax::ast::{ty_u16, ty_u32, ty_u64, ty_u8, ty_uint, type_value_ns}; @@ -115,7 +115,6 @@ impl PatternBindingMode : cmp::Eq { enum Namespace { - ModuleNS, TypeNS, ValueNS } @@ -166,19 +165,8 @@ enum CaptureClause { type ResolveVisitor = vt<()>; -enum ModuleDef { - NoModuleDef, // Does not define a module. - ModuleDef(Privacy, @Module), // Defines a module. -} - -impl ModuleDef { - pure fn is_none() -> bool { - match self { NoModuleDef => true, _ => false } - } -} - enum ImportDirectiveNS { - ModuleNSOnly, + TypeNSOnly, AnyNS } @@ -363,7 +351,6 @@ struct ImportResolution { mut outstanding_references: uint, - mut module_target: Option, mut value_target: Option, mut type_target: Option, @@ -375,7 +362,6 @@ fn ImportResolution(privacy: Privacy, span: span) -> ImportResolution { privacy: privacy, span: span, outstanding_references: 0u, - module_target: None, value_target: None, type_target: None, used: false @@ -385,7 +371,6 @@ fn ImportResolution(privacy: Privacy, span: span) -> ImportResolution { impl ImportResolution { fn target_for_namespace(namespace: Namespace) -> Option { match namespace { - ModuleNS => return copy self.module_target, TypeNS => return copy self.type_target, ValueNS => return copy self.value_target } @@ -482,7 +467,7 @@ pure fn is_none(x: Option) -> bool { } } -fn unused_import_lint_level(session: session) -> level { +fn unused_import_lint_level(session: Session) -> level { for session.opts.lint_opts.each |lint_option_pair| { let (lint_type, lint_level) = *lint_option_pair; if lint_type == unused_imports { @@ -504,8 +489,14 @@ impl Privacy : cmp::Eq { pure fn ne(other: &Privacy) -> bool { !self.eq(other) } } -// Records a possibly-private definition. -struct Definition { +// Records a possibly-private type definition. +enum TypeNsDef { + ModuleDef(Privacy, @Module), + TypeDef(Privacy, def) +} + +// Records a possibly-private value definition. +struct ValueNsDef { privacy: Privacy, def: def, } @@ -513,13 +504,11 @@ struct Definition { // Records the definitions (at most one for each namespace) that a name is // bound to. struct NameBindings { - mut module_def: ModuleDef, //< Meaning in module namespace. - mut type_def: Option, //< Meaning in type namespace. - mut value_def: Option, //< Meaning in value namespace. + mut type_def: Option, //< Meaning in type namespace. + mut value_def: Option, //< Meaning in value namespace. // For error reporting - // XXX: Merge me into Definition. - mut module_span: Option, + // XXX: Merge me into TypeDef and ValueDef. mut type_span: Option, mut value_span: Option, } @@ -532,30 +521,30 @@ impl NameBindings { def_id: Option, legacy_exports: bool, sp: span) { - if self.module_def.is_none() { + if self.type_def.is_none() { let module_ = @Module(parent_link, def_id, legacy_exports); - self.module_def = ModuleDef(privacy, module_); - self.module_span = Some(sp); + self.type_def = Some(ModuleDef(privacy, module_)); + self.type_span = Some(sp); } } /// Records a type definition. fn define_type(privacy: Privacy, def: def, sp: span) { - self.type_def = Some(Definition { privacy: privacy, def: def }); + self.type_def = Some(TypeDef(privacy, def)); self.type_span = Some(sp); } /// Records a value definition. fn define_value(privacy: Privacy, def: def, sp: span) { - self.value_def = Some(Definition { privacy: privacy, def: def }); + self.value_def = Some(ValueNsDef { privacy: privacy, def: def }); self.value_span = Some(sp); } /// Returns the module node if applicable. fn get_module_if_available() -> Option<@Module> { - match self.module_def { - NoModuleDef => return None, - ModuleDef(_privacy, module_) => return Some(module_) + match self.type_def { + Some(ModuleDef(_, module_)) => return Some(module_), + None | Some(TypeDef(_, _)) => return None, } } @@ -564,70 +553,76 @@ impl NameBindings { * definition. */ fn get_module() -> @Module { - match self.module_def { - NoModuleDef => { - fail - ~"get_module called on a node with no module definition!"; - } - ModuleDef(_, module_) => { - return module_; + match self.type_def { + None | Some(TypeDef(*)) => { + fail ~"get_module called on a node with no module \ + definition!" } + Some(ModuleDef(_, module_)) => module_ } } fn defined_in_namespace(namespace: Namespace) -> bool { match namespace { - ModuleNS => { - match self.module_def { - NoModuleDef => false, - _ => true - } - } TypeNS => return self.type_def.is_some(), ValueNS => return self.value_def.is_some() } } - fn def_for_namespace(namespace: Namespace) -> Option { + fn def_for_namespace(namespace: Namespace) -> Option { match namespace { - TypeNS => return self.type_def, - ValueNS => return self.value_def, - ModuleNS => match self.module_def { - NoModuleDef => return None, - ModuleDef(privacy, module_) => - match module_.def_id { - None => return None, - Some(def_id) => { - return Some(Definition { - privacy: privacy, - def: def_mod(def_id) - }); + TypeNS => { + match self.type_def { + None => None, + Some(ModuleDef(_, module_)) => { + module_.def_id.map(|def_id| def_mod(*def_id)) } + Some(TypeDef(_, def)) => Some(def) } - } + } + ValueNS => { + match self.value_def { + None => None, + Some(value_def) => Some(value_def.def) + } + } + } + } + + fn privacy_for_namespace(namespace: Namespace) -> Option { + match namespace { + TypeNS => { + match self.type_def { + None => None, + Some(ModuleDef(privacy, _)) | Some(TypeDef(privacy, _)) => + Some(privacy) + } + } + ValueNS => { + match self.value_def { + None => None, + Some(value_def) => Some(value_def.privacy) + } + } } } fn span_for_namespace(namespace: Namespace) -> Option { - match self.def_for_namespace(namespace) { - Some(_) => { + if self.defined_in_namespace(namespace) { match namespace { - TypeNS => self.type_span, - ValueNS => self.value_span, - ModuleNS => self.module_span + TypeNS => self.type_span, + ValueNS => self.value_span, } - } - None => None + } else { + None } } } fn NameBindings() -> NameBindings { NameBindings { - module_def: NoModuleDef, type_def: None, value_def: None, - module_span: None, type_span: None, value_span: None } @@ -675,9 +670,8 @@ fn PrimitiveTypeTable(intr: @ident_interner) -> PrimitiveTypeTable { fn namespace_to_str(ns: Namespace) -> ~str { match ns { - TypeNS => ~"type", - ValueNS => ~"value", - ModuleNS => ~"module" + TypeNS => ~"type", + ValueNS => ~"value", } } @@ -693,9 +687,8 @@ fn has_legacy_export_attr(attrs: &[syntax::ast::attribute]) -> bool { return false; } -fn Resolver(session: session, lang_items: LanguageItems, +fn Resolver(session: Session, lang_items: LanguageItems, crate: @crate) -> Resolver { - let graph_root = @NameBindings(); (*graph_root).define_module(Public, @@ -735,7 +728,7 @@ fn Resolver(session: session, lang_items: LanguageItems, primitive_type_table: @PrimitiveTypeTable(session. parse_sess.interner), - namespaces: ~[ ModuleNS, TypeNS, ValueNS ], + namespaces: ~[ TypeNS, ValueNS ], def_map: HashMap(), export_map2: HashMap(), @@ -749,7 +742,7 @@ fn Resolver(session: session, lang_items: LanguageItems, /// The main resolver class. struct Resolver { - session: session, + session: Session, lang_items: LanguageItems, crate: @crate, @@ -992,14 +985,14 @@ impl Resolver { match item.node { item_mod(module_) => { - let legacy = has_legacy_export_attr(item.attrs); - let (name_bindings, new_parent) = self.add_child(ident, parent, - ~[ModuleNS], sp); + let legacy = has_legacy_export_attr(item.attrs); + let (name_bindings, new_parent) = + self.add_child(ident, parent, ~[TypeNS], sp); let parent_link = self.get_parent_link(new_parent, ident); let def_id = { crate: 0, node: item.id }; - (*name_bindings).define_module(privacy, parent_link, - Some(def_id), legacy, sp); + (*name_bindings).define_module(privacy, parent_link, + Some(def_id), legacy, sp); let new_parent = ModuleReducedGraphParent((*name_bindings).get_module()); @@ -1007,25 +1000,30 @@ impl Resolver { visit_mod(module_, sp, item.id, new_parent, visitor); } item_foreign_mod(fm) => { - let legacy = has_legacy_export_attr(item.attrs); - let new_parent = match fm.sort { - named => { - let (name_bindings, new_parent) = self.add_child(ident, - parent, ~[ModuleNS], sp); + let legacy = has_legacy_export_attr(item.attrs); + let new_parent = match fm.sort { + named => { + let (name_bindings, new_parent) = + self.add_child(ident, parent, ~[TypeNS], sp); - let parent_link = self.get_parent_link(new_parent, ident); - let def_id = { crate: 0, node: item.id }; - (*name_bindings).define_module(privacy, parent_link, - Some(def_id), legacy, sp); + let parent_link = self.get_parent_link(new_parent, + ident); + let def_id = { crate: 0, node: item.id }; + (*name_bindings).define_module(privacy, + parent_link, + Some(def_id), + legacy, + sp); - ModuleReducedGraphParent((*name_bindings).get_module()) - } - // For anon foreign mods, the contents just go in the - // current scope - anonymous => parent - }; + ModuleReducedGraphParent(name_bindings.get_module()) + } - visit_item(item, new_parent, visitor); + // For anon foreign mods, the contents just go in the + // current scope + anonymous => parent + }; + + visit_item(item, new_parent, visitor); } // These items live in the value namespace. @@ -1226,7 +1224,7 @@ impl Resolver { match view_path.node { view_path_simple(binding, full_path, ns, _) => { let ns = match ns { - module_ns => ModuleNSOnly, + module_ns => TypeNSOnly, type_value_ns => AnyNS }; @@ -1326,8 +1324,7 @@ impl Resolver { match find_use_stmt_cnum(self.session.cstore, node_id) { Some(crate_id) => { let (child_name_bindings, new_parent) = - // should this be in ModuleNS? --tjc - self.add_child(name, parent, ~[ModuleNS], + self.add_child(name, parent, ~[TypeNS], view_item.span); let def_id = { crate: crate_id, node: 0 }; @@ -1410,8 +1407,8 @@ impl Resolver { ident: ident, new_parent: ReducedGraphParent) { match def { def_mod(def_id) | def_foreign_mod(def_id) => { - match copy child_name_bindings.module_def { - NoModuleDef => { + match copy child_name_bindings.type_def { + None => { debug!("(building reduced graph for \ external crate) building module \ %s", final_ident); @@ -1441,10 +1438,8 @@ impl Resolver { fail ~"can't happen"; } ModuleParentLink(parent_module, ident) => { - let name_bindings = parent_module.children.get(ident); - - resolution.module_target = + resolution.type_target = Some(Target(parent_module, name_bindings)); } } @@ -1456,13 +1451,16 @@ impl Resolver { } } } - ModuleDef(_priv, module_) => { + Some(ModuleDef(_, module_)) => { debug!("(building reduced graph for \ external crate) already created \ module"); module_.def_id = Some(def_id); modules.insert(def_id, module_); } + Some(TypeDef(*)) => { + self.session.bug(~"external module def overwriting type def"); + } } } def_fn(*) | def_static_method(*) | def_const(*) | @@ -1553,8 +1551,8 @@ impl Resolver { ~[], dummy_sp()); // Define or reuse the module node. - match child_name_bindings.module_def { - NoModuleDef => { + match child_name_bindings.type_def { + None => { debug!("(building reduced graph for external crate) \ autovivifying %s", *ident_str); let parent_link = self.get_parent_link(new_parent, @@ -1564,7 +1562,7 @@ impl Resolver { None, false, dummy_sp()); } - ModuleDef(*) => { /* Fall through. */ } + Some(_) => { /* Fall through. */ } } current_module = (*child_name_bindings).get_module(); @@ -1807,7 +1805,7 @@ impl Resolver { target, source); } - SingleImport(target, source, ModuleNSOnly) => { + SingleImport(target, source, TypeNSOnly) => { resolution_result = self.resolve_single_module_import (module_, containing_module, target, @@ -1876,12 +1874,11 @@ impl Resolver { return Failed; } - // We need to resolve all four namespaces for this to succeed. + // We need to resolve both namespaces for this to succeed. // // XXX: See if there's some way of handling namespaces in a more - // generic way. We have four of them; it seems worth doing... + // generic way. We have two of them; it seems worth doing... - let mut module_result = UnknownResult; let mut value_result = UnknownResult; let mut type_result = UnknownResult; @@ -1891,10 +1888,6 @@ impl Resolver { // Continue. } Some(child_name_bindings) => { - if (*child_name_bindings).defined_in_namespace(ModuleNS) { - module_result = BoundResult(containing_module, - child_name_bindings); - } if (*child_name_bindings).defined_in_namespace(ValueNS) { value_result = BoundResult(containing_module, child_name_bindings); @@ -1906,11 +1899,10 @@ impl Resolver { } } - // Unless we managed to find a result in all four namespaces - // (exceedingly unlikely), search imports as well. - - match (module_result, value_result, type_result) { - (BoundResult(*), BoundResult(*), BoundResult(*)) => { + // Unless we managed to find a result in both namespaces (unlikely), + // search imports as well. + match (value_result, type_result) { + (BoundResult(*), BoundResult(*)) => { // Continue. } _ => { @@ -1934,9 +1926,6 @@ impl Resolver { // therefore accurately report that the names are // unbound. - if module_result.is_unknown() { - module_result = UnboundResult; - } if value_result.is_unknown() { value_result = UnboundResult; } @@ -1973,11 +1962,6 @@ impl Resolver { // The name is an import which has been fully // resolved. We can, therefore, just follow it. - - if module_result.is_unknown() { - module_result = get_binding(import_resolution, - ModuleNS); - } if value_result.is_unknown() { value_result = get_binding(import_resolution, ValueNS); @@ -2001,20 +1985,6 @@ impl Resolver { assert module_.import_resolutions.contains_key(target); let import_resolution = module_.import_resolutions.get(target); - match module_result { - BoundResult(target_module, name_bindings) => { - debug!("(resolving single import) found module binding"); - import_resolution.module_target = - Some(Target(target_module, name_bindings)); - } - UnboundResult => { - debug!("(resolving single import) didn't find module \ - binding"); - } - UnknownResult => { - fail ~"module result should be known at this point"; - } - } match value_result { BoundResult(target_module, name_bindings) => { import_resolution.value_target = @@ -2037,12 +2007,10 @@ impl Resolver { } let i = import_resolution; - match (i.module_target, i.value_target, i.type_target) { - /* - If this name wasn't found in any of the four namespaces, it's - definitely unresolved - */ - (None, None, None) => { return Failed; } + match (i.value_target, i.type_target) { + // If this name wasn't found in either namespace, it's definitely + // unresolved. + (None, None) => { return Failed; } _ => {} } @@ -2081,7 +2049,7 @@ impl Resolver { // Continue. } Some(child_name_bindings) => { - if (*child_name_bindings).defined_in_namespace(ModuleNS) { + if (*child_name_bindings).defined_in_namespace(TypeNS) { module_result = BoundResult(containing_module, child_name_bindings); } @@ -2125,8 +2093,8 @@ impl Resolver { // resolved. We can, therefore, just follow it. if module_result.is_unknown() { - match (*import_resolution). - target_for_namespace(ModuleNS) { + match (*import_resolution).target_for_namespace( + TypeNS) { None => { module_result = UnboundResult; } @@ -2156,7 +2124,7 @@ impl Resolver { match module_result { BoundResult(target_module, name_bindings) => { debug!("(resolving single import) found module binding"); - import_resolution.module_target = + import_resolution.type_target = Some(Target(target_module, name_bindings)); } UnboundResult => { @@ -2169,8 +2137,8 @@ impl Resolver { } let i = import_resolution; - if i.module_target.is_none() { - // If this name wasn't found in the module namespace, it's + if i.type_target.is_none() { + // If this name wasn't found in the type namespace, it's // definitely unresolved. return Failed; } @@ -2222,7 +2190,7 @@ impl Resolver { debug!("(resolving glob import) writing module resolution \ %? into `%s`", - is_none(target_import_resolution.module_target), + is_none(target_import_resolution.type_target), self.module_to_str(module_)); // Here we merge two import resolutions. @@ -2232,8 +2200,6 @@ impl Resolver { let new_import_resolution = @ImportResolution(privacy, target_import_resolution.span); - new_import_resolution.module_target = - copy target_import_resolution.module_target; new_import_resolution.value_target = copy target_import_resolution.value_target; new_import_resolution.type_target = @@ -2246,15 +2212,6 @@ impl Resolver { // Merge the two import resolutions at a finer-grained // level. - match copy target_import_resolution.module_target { - None => { - // Continue. - } - Some(module_target) => { - dest_import_resolution.module_target = - Some(copy module_target); - } - } match copy target_import_resolution.value_target { None => { // Continue. @@ -2307,11 +2264,6 @@ impl Resolver { self.module_to_str(module_)); // Merge the child item into the import resolution. - if (*name_bindings).defined_in_namespace(ModuleNS) { - debug!("(resolving glob import) ... for module target"); - dest_import_resolution.module_target = - Some(Target(containing_module, name_bindings)); - } if (*name_bindings).defined_in_namespace(ValueNS) { debug!("(resolving glob import) ... for value target"); dest_import_resolution.value_target = @@ -2345,9 +2297,8 @@ impl Resolver { while index < module_path_len { let name = (*module_path).get_elt(index); - match self.resolve_name_in_module(search_module, name, ModuleNS, - xray) { - + match self.resolve_name_in_module(search_module, name, TypeNS, + xray) { Failed => { self.session.span_err(span, ~"unresolved name"); return Failed; @@ -2359,8 +2310,8 @@ impl Resolver { return Indeterminate; } Success(target) => { - match target.bindings.module_def { - NoModuleDef => { + match target.bindings.type_def { + None | Some(TypeDef(*)) => { // Not a module. self.session.span_err(span, fmt!("not a module: %s", @@ -2368,7 +2319,7 @@ impl Resolver { str_of(name))); return Failed; } - ModuleDef(_, copy module_) => { + Some(ModuleDef(_, copy module_)) => { search_module = module_; } } @@ -2443,7 +2394,6 @@ impl Resolver { match module_.children.find(name) { Some(name_bindings) if (*name_bindings).defined_in_namespace(namespace) => { - return Success(Target(module_, name_bindings)); } Some(_) | None => { /* Not found; continue. */ } @@ -2516,15 +2466,15 @@ impl Resolver { fn resolve_module_in_lexical_scope(module_: @Module, name: ident) -> ResolveResult<@Module> { - match self.resolve_item_in_lexical_scope(module_, name, ModuleNS) { + match self.resolve_item_in_lexical_scope(module_, name, TypeNS) { Success(target) => { - match target.bindings.module_def { - NoModuleDef => { + match target.bindings.type_def { + None | Some(TypeDef(*)) => { error!("!!! (resolving module in lexical scope) module wasn't actually a module!"); return Failed; } - ModuleDef(_, module_) => { + Some(ModuleDef(_, module_)) => { return Success(module_); } } @@ -2661,8 +2611,7 @@ impl Resolver { debug!("(resolving one-level naming result) searching for module"); match self.resolve_item_in_lexical_scope(module_, source_name, - ModuleNS) { - + TypeNS) { Failed => { debug!("(resolving one-level renaming import) didn't find \ module result"); @@ -2682,7 +2631,7 @@ impl Resolver { let mut value_result; let mut type_result; - if allowable_namespaces == ModuleNSOnly { + if allowable_namespaces == TypeNSOnly { value_result = None; type_result = None; } else { @@ -2772,7 +2721,6 @@ impl Resolver { self.session.str_of(target_name), self.module_to_str(module_)); - import_resolution.module_target = module_result; import_resolution.value_target = value_result; import_resolution.type_target = type_result; @@ -2885,18 +2833,19 @@ impl Resolver { ident: ident, namebindings: @NameBindings, reexport: bool) { - for [ModuleNS, TypeNS, ValueNS].each |ns| { - match namebindings.def_for_namespace(*ns) { - Some(d) if d.privacy == Public => { + for [ TypeNS, ValueNS ].each |ns| { + match (namebindings.def_for_namespace(*ns), + namebindings.privacy_for_namespace(*ns)) { + (Some(d), Some(Public)) => { debug!("(computing exports) YES: %s '%s' \ => %?", if reexport { ~"reexport" } else { ~"export"}, self.session.str_of(ident), - def_id_of_def(d.def)); + def_id_of_def(d)); exports2.push(Export2 { reexport: reexport, name: self.session.str_of(ident), - def_id: def_id_of_def(d.def) + def_id: def_id_of_def(d) }); } _ => () @@ -2914,12 +2863,13 @@ impl Resolver { } for module_.import_resolutions.each_ref |ident, importresolution| { - for [ModuleNS, TypeNS, ValueNS].each |ns| { + for [ TypeNS, ValueNS ].each |ns| { match importresolution.target_for_namespace(*ns) { Some(target) => { debug!("(computing exports) maybe reexport '%s'", self.session.str_of(*ident)); - self.add_exports_of_namebindings(exports2, *ident, + self.add_exports_of_namebindings(exports2, + *ident, target.bindings, true) } @@ -3666,7 +3616,7 @@ impl Resolver { span: span, type_parameters: ~[ty_param], opt_trait_reference: Option<@trait_ref>, - self_type: @ty, + self_type: @Ty, methods: ~[@method], visitor: ResolveVisitor) { @@ -3864,7 +3814,7 @@ impl Resolver { debug!("(resolving block) leaving block"); } - fn resolve_type(ty: @ty, visitor: ResolveVisitor) { + fn resolve_type(ty: @Ty, visitor: ResolveVisitor) { match ty.node { // Like path expressions, the interpretation of path types depends // on whether the path has multiple elements in it or not. @@ -3872,42 +3822,44 @@ impl Resolver { ty_path(path, path_id) => { // This is a path in the type namespace. Walk through scopes // scopes looking for it. + let mut result_def = None; - let mut result_def; - match self.resolve_path(path, TypeNS, true, visitor) { - Some(def) => { - debug!("(resolving type) resolved `%s` to type", - self.session.str_of(path.idents.last())); - result_def = Some(def); - } - None => { - result_def = None; + // First, check to see whether the name is a primitive type. + if path.idents.len() == 1u { + let name = path.idents.last(); + + match self.primitive_type_table + .primitive_types + .find(name) { + + Some(primitive_type) => { + result_def = + Some(def_prim_ty(primitive_type)); + } + None => { + // Continue. + } } } match result_def { - Some(_) => { - // Continue. - } None => { - // Check to see whether the name is a primitive type. - if path.idents.len() == 1u { - let name = path.idents.last(); - - match self.primitive_type_table - .primitive_types - .find(name) { - - Some(primitive_type) => { - result_def = - Some(def_prim_ty(primitive_type)); - } - None => { - // Continue. - } + match self.resolve_path(path, TypeNS, true, visitor) { + Some(def) => { + debug!("(resolving type) resolved `%s` to \ + type", + self.session.str_of( + path.idents.last())); + result_def = Some(def); + } + None => { + result_def = None; } } } + Some(_) => { + // Continue. + } } match copy result_def { @@ -4223,12 +4175,17 @@ impl Resolver { // First, search children. match containing_module.children.find(name) { Some(child_name_bindings) => { - match (*child_name_bindings).def_for_namespace(namespace) { - Some(def) if def.privacy == Public || xray == Xray => { + match (child_name_bindings.def_for_namespace(namespace), + child_name_bindings.privacy_for_namespace(namespace)) { + (Some(def), Some(Public)) => { // Found it. Stop the search here. - return ChildNameDefinition(def.def); + return ChildNameDefinition(def); } - Some(_) | None => { + (Some(def), _) if xray == Xray => { + // Found it. Stop the search here. + return ChildNameDefinition(def); + } + (Some(_), _) | (None, _) => { // Continue. } } @@ -4244,14 +4201,15 @@ impl Resolver { xray == Xray => { match (*import_resolution).target_for_namespace(namespace) { Some(target) => { - match (*target.bindings) - .def_for_namespace(namespace) { - Some(def) if def.privacy == Public => { + match (target.bindings.def_for_namespace(namespace), + target.bindings.privacy_for_namespace( + namespace)) { + (Some(def), Some(Public)) => { // Found it. import_resolution.used = true; - return ImportNameDefinition(def.def); + return ImportNameDefinition(def); } - Some(_) | None => { + (Some(_), _) | (None, _) => { // This can happen with external impls, due to // the imperfect way we read the metadata. @@ -4391,9 +4349,6 @@ impl Resolver { search_result = self.search_ribs(self.type_ribs, ident, span, AllowCapturingSelf); } - ModuleNS => { - fail ~"module namespaces do not have local ribs"; - } } match copy search_result { @@ -4413,23 +4368,22 @@ impl Resolver { fn resolve_item_by_identifier_in_lexical_scope(ident: ident, namespace: Namespace) -> Option { - // Check the items. match self.resolve_item_in_lexical_scope(self.current_module, ident, namespace) { - Success(target) => { match (*target.bindings).def_for_namespace(namespace) { None => { - fail ~"resolved name in a namespace to a set of name \ - bindings with no def for that namespace?!"; + // This can happen if we were looking for a type and + // found a module instead. Modules don't have defs. + return None; } Some(def) => { debug!("(resolving item path in lexical scope) \ resolved `%s` to item", self.session.str_of(ident)); - return Some(def.def); + return Some(def); } } } @@ -4703,7 +4657,7 @@ impl Resolver { for search_module.children.each |_name, child_name_bindings| { match child_name_bindings.def_for_namespace(TypeNS) { Some(def) => { - match def.def { + match def { def_ty(trait_def_id) => { self.add_trait_info_if_containing_method( found_traits, trait_def_id, name); @@ -4730,7 +4684,7 @@ impl Resolver { Some(target) => { match target.bindings.def_for_namespace(TypeNS) { Some(def) => { - match def.def { + match def { def_ty(trait_def_id) => { self. add_trait_info_if_containing_method( @@ -4937,15 +4891,6 @@ impl Resolver { debug!("Import resolutions:"); for module_.import_resolutions.each |name, import_resolution| { - let mut module_repr; - match (*import_resolution).target_for_namespace(ModuleNS) { - None => { module_repr = ~""; } - Some(_) => { - module_repr = ~" module:?"; - // XXX - } - } - let mut value_repr; match (*import_resolution).target_for_namespace(ValueNS) { None => { value_repr = ~""; } @@ -4964,15 +4909,14 @@ impl Resolver { } } - debug!("* %s:%s%s%s", - self.session.str_of(name), - module_repr, value_repr, type_repr); + debug!("* %s:%s%s", self.session.str_of(name), + value_repr, type_repr); } } } /// Entry point to crate resolution. -fn resolve_crate(session: session, lang_items: LanguageItems, crate: @crate) +fn resolve_crate(session: Session, lang_items: LanguageItems, crate: @crate) -> { def_map: DefMap, exp_map2: ExportMap2, trait_map: TraitMap } { diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index 50ea80a134cb..d760bc349073 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -99,7 +99,6 @@ * */ -use driver::session::session; use lib::llvm::llvm; use lib::llvm::{ValueRef, BasicBlockRef}; use pat_util::*; diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 93e8435d3e95..4c9a006007e7 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -17,7 +17,7 @@ use libc::{c_uint, c_ulonglong}; use std::{map, time, list}; use std::map::HashMap; use driver::session; -use session::session; +use session::Session; use syntax::attr; use back::{link, abi, upcall}; use syntax::{ast, ast_util, codemap, ast_map}; @@ -2377,7 +2377,7 @@ fn create_module_map(ccx: @crate_ctxt) -> ValueRef { } -fn decl_crate_map(sess: session::session, mapmeta: link_meta, +fn decl_crate_map(sess: session::Session, mapmeta: link_meta, llmod: ModuleRef) -> ValueRef { let targ_cfg = sess.targ_cfg; let int_type = T_int(targ_cfg); @@ -2482,7 +2482,7 @@ fn write_abi_version(ccx: @crate_ctxt) { false); } -fn trans_crate(sess: session::session, +fn trans_crate(sess: session::Session, crate: @ast::crate, tcx: ty::ctxt, output: &Path, diff --git a/src/rustc/middle/trans/build.rs b/src/rustc/middle/trans/build.rs index 69de8a2cca3e..dfcc66adc3ac 100644 --- a/src/rustc/middle/trans/build.rs +++ b/src/rustc/middle/trans/build.rs @@ -6,7 +6,6 @@ use codemap::span; use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef}; use lib::llvm::{Opcode, IntPredicate, RealPredicate, True, False, CallConv, TypeKind, AtomicBinOp, AtomicOrdering}; -use driver::session::session; use common::*; fn B(cx: block) -> BuilderRef { diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 0fa22dd65ba7..931e82d5be98 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -8,7 +8,7 @@ use vec::raw::to_ptr; use std::map::{HashMap,Set}; use syntax::{ast, ast_map}; use driver::session; -use session::session; +use session::Session; use middle::ty; use back::{link, abi, upcall}; use syntax::codemap::span; @@ -110,7 +110,7 @@ fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res { // Crate context. Every crate we compile has one of these. type crate_ctxt = { - sess: session::session, + sess: session::Session, llmod: ModuleRef, td: target_data, tn: type_names, @@ -605,7 +605,7 @@ fn block_parent(cx: block) -> block { impl block { pure fn ccx() -> @crate_ctxt { self.fcx.ccx } pure fn tcx() -> ty::ctxt { self.fcx.ccx.tcx } - pure fn sess() -> session { self.fcx.ccx.sess } + pure fn sess() -> Session { self.fcx.ccx.sess } fn node_id_to_str(id: ast::node_id) -> ~str { ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr()) @@ -1191,7 +1191,7 @@ fn align_to(cx: block, off: ValueRef, align: ValueRef) -> ValueRef { return build::And(cx, bumped, build::Not(cx, mask)); } -fn path_str(sess: session::session, p: path) -> ~str { +fn path_str(sess: session::Session, p: path) -> ~str { let mut r = ~"", first = true; for vec::each(p) |e| { match *e { diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs index 068ec49d6c7e..2db0dd59cf91 100644 --- a/src/rustc/middle/trans/debuginfo.rs +++ b/src/rustc/middle/trans/debuginfo.rs @@ -9,7 +9,7 @@ use middle::ty; use syntax::{ast, codemap, ast_util, ast_map}; use syntax::parse::token::ident_interner; use codemap::span; -use ast::ty; +use ast::Ty; use pat_util::*; use util::ppaux::ty_to_str; use driver::session::session; @@ -229,7 +229,7 @@ fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata { return mdval; } -fn line_from_span(cm: codemap::codemap, sp: span) -> uint { +fn line_from_span(cm: codemap::CodeMap, sp: span) -> uint { codemap::lookup_char_pos(cm, sp.lo).line } @@ -469,7 +469,7 @@ fn create_composite_type(type_tag: int, name: ~str, file: ValueRef, line: int, } fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t, - vec_ty_span: codemap::span, elem_ty: @ast::ty) + vec_ty_span: codemap::span, elem_ty: @ast::Ty) -> @metadata { let fname = filename_from_span(cx, vec_ty_span); let file_node = create_file(cx, fname); @@ -492,7 +492,7 @@ fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t, return @{node: llnode, data: {hash: ty::type_id(vec_t)}}; } -fn create_ty(_cx: @crate_ctxt, _t: ty::t, _ty: @ast::ty) +fn create_ty(_cx: @crate_ctxt, _t: ty::t, _ty: @ast::Ty) -> @metadata { /*let cache = get_cache(cx); match cached_metadata::<@metadata>( diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index 5a6260ae2700..8a03884f415c 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -1,7 +1,7 @@ // The classification code for the x86_64 ABI is taken from the clay language // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp -use driver::session::{session, arch_x86_64}; +use driver::session::arch_x86_64; use syntax::codemap::span; use libc::c_uint; use syntax::{attr, ast_map}; diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs index bfb8de76a6c5..a99ef96b2544 100644 --- a/src/rustc/middle/trans/reachable.rs +++ b/src/rustc/middle/trans/reachable.rs @@ -128,7 +128,7 @@ fn mk_ty_visitor() -> visit::vt { visit::mk_vt(@{visit_ty: traverse_ty, ..*visit::default_visitor()}) } -fn traverse_ty(ty: @ty, cx: ctx, v: visit::vt) { +fn traverse_ty(ty: @Ty, cx: ctx, v: visit::vt) { if cx.rmap.contains_key(ty.id) { return; } cx.rmap.insert(ty.id, ()); diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index c105caecaebb..18a25888bb46 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -1,5 +1,4 @@ use std::map::HashMap; -use driver::session::session; use lib::llvm::{TypeRef, ValueRef}; use syntax::ast; use back::abi; diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index b78314a67478..149c6ea532d4 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -1,5 +1,4 @@ use syntax::ast; -use driver::session::session; use lib::llvm::{ValueRef, TypeRef}; use back::abi; use syntax::codemap::span; diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 8ccc8a28de3a..8b2efacd4d16 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -20,7 +20,6 @@ use std::map::HashMap; use std::list; use std::list::{List, Cons, Nil}; -use driver::session::session; use metadata::csearch; use syntax::ast::*, syntax::ast_util, syntax::visit; use syntax::ast_map; diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index a0ca46ee0178..84510c7161e3 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -5,7 +5,7 @@ use std::{map, smallintmap}; use result::Result; use std::map::HashMap; use driver::session; -use session::session; +use session::Session; use syntax::{ast, ast_map}; use syntax::ast_util; use syntax::ast_util::{is_local, local_def}; @@ -103,7 +103,7 @@ export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var; export InferTy, TyVar, IntVar; export ty_self, mk_self, type_has_self; export ty_class; -export region, bound_region, encl_region; +export Region, bound_region, encl_region; export re_bound, re_free, re_scope, re_static, re_var; export br_self, br_anon, br_named, br_cap_avoid; export get, type_has_params, type_needs_infer, type_has_regions; @@ -114,7 +114,7 @@ export ty_var_id; export ty_to_def_id; export ty_fn_args; export ty_region; -export kind, kind_implicitly_copyable, kind_send_copy, kind_copyable; +export Kind, kind_implicitly_copyable, kind_send_copy, kind_copyable; export kind_noncopyable, kind_const; export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied; export kind_is_safe_for_default_mode; @@ -219,7 +219,7 @@ enum vstore { vstore_fixed(uint), vstore_uniq, vstore_box, - vstore_slice(region) + vstore_slice(Region) } type field_ty = { @@ -302,7 +302,7 @@ type AutoAdjustment = { #[auto_deserialize] type AutoRef = { kind: AutoRefKind, - region: region, + region: Region, mutbl: ast::mutability }; @@ -327,8 +327,8 @@ type ctxt = mut next_id: uint, vecs_implicitly_copyable: bool, legacy_modes: bool, - cstore: metadata::cstore::cstore, - sess: session::session, + cstore: metadata::cstore::CStore, + sess: session::Session, def_map: resolve::DefMap, region_map: middle::region::region_map, @@ -354,8 +354,8 @@ type ctxt = short_names_cache: HashMap, needs_drop_cache: HashMap, needs_unwind_cleanup_cache: HashMap, - kind_cache: HashMap, - ast_ty_to_ty_cache: HashMap<@ast::ty, ast_ty_to_ty_cache_entry>, + kind_cache: HashMap, + ast_ty_to_ty_cache: HashMap<@ast::Ty, ast_ty_to_ty_cache_entry>, enum_var_cache: HashMap, trait_method_cache: HashMap, ty_param_bounds: HashMap, @@ -519,7 +519,7 @@ impl param_ty : to_bytes::IterBytes { /// Representation of regions: #[auto_serialize] #[auto_deserialize] -enum region { +enum Region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions /// (analogous to type parameters, except that due to the monomorphic @@ -570,7 +570,7 @@ enum bound_region { br_cap_avoid(ast::node_id, @bound_region), } -type opt_region = Option; +type opt_region = Option; /** * The type substs represents the kinds of things that can be substituted to @@ -610,7 +610,7 @@ enum sty { ty_uniq(mt), ty_evec(mt, vstore), ty_ptr(mt), - ty_rptr(region, mt), + ty_rptr(Region, mt), ty_rec(~[field]), ty_fn(FnTy), ty_trait(def_id, substs, vstore), @@ -656,9 +656,9 @@ enum type_err { terr_record_fields(expected_found), terr_arg_count, terr_mode_mismatch(expected_found), - terr_regions_does_not_outlive(region, region), - terr_regions_not_same(region, region), - terr_regions_no_overlap(region, region), + terr_regions_does_not_outlive(Region, Region), + terr_regions_not_same(Region, Region), + terr_regions_no_overlap(Region, Region), terr_vstores_differ(terr_vstore_kind, expected_found), terr_in_field(@type_err, ast::ident), terr_sorts(expected_found), @@ -783,7 +783,7 @@ impl FnVid : to_bytes::IterBytes { } } -fn param_bounds_to_kind(bounds: param_bounds) -> kind { +fn param_bounds_to_kind(bounds: param_bounds) -> Kind { let mut kind = kind_noncopyable(); for vec::each(*bounds) |bound| { match *bound { @@ -834,7 +834,7 @@ fn new_ty_hash() -> map::HashMap { map::HashMap() } -fn mk_ctxt(s: session::session, +fn mk_ctxt(s: session::Session, dm: resolve::DefMap, amap: ast_map::map, freevars: freevars::freevar_map, @@ -904,7 +904,7 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { _ => () } let mut flags = 0u; - fn rflags(r: region) -> uint { + fn rflags(r: Region) -> uint { (has_regions as uint) | { match r { ty::re_var(_) => needs_infer as uint, @@ -1018,12 +1018,12 @@ fn mk_imm_uniq(cx: ctxt, ty: t) -> t { mk_uniq(cx, {ty: ty, fn mk_ptr(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) } -fn mk_rptr(cx: ctxt, r: region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) } +fn mk_rptr(cx: ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) } -fn mk_mut_rptr(cx: ctxt, r: region, ty: t) -> t { +fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t { mk_rptr(cx, r, {ty: ty, mutbl: ast::m_mutbl}) } -fn mk_imm_rptr(cx: ctxt, r: region, ty: t) -> t { +fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t { mk_rptr(cx, r, {ty: ty, mutbl: ast::m_imm}) } @@ -1148,7 +1148,7 @@ fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { // Returns the narrowest lifetime enclosing the evaluation of the expression // with id `id`. -fn encl_region(cx: ctxt, id: ast::node_id) -> ty::region { +fn encl_region(cx: ctxt, id: ast::node_id) -> ty::Region { match cx.region_map.find(id) { Some(encl_scope) => ty::re_scope(encl_scope), None => ty::re_static @@ -1265,7 +1265,7 @@ fn fold_ty(cx: ctxt, t0: t, fldop: fn(t) -> t) -> t { fn walk_regions_and_ty( cx: ctxt, ty: t, - walkr: fn(r: region), + walkr: fn(r: Region), walkt: fn(t: t) -> bool) { if (walkt(ty)) { @@ -1280,13 +1280,13 @@ fn walk_regions_and_ty( fn fold_regions_and_ty( cx: ctxt, ty: t, - fldr: fn(r: region) -> region, + fldr: fn(r: Region) -> Region, fldfnt: fn(t: t) -> t, fldt: fn(t: t) -> t) -> t { fn fold_substs( substs: &substs, - fldr: fn(r: region) -> region, + fldr: fn(r: Region) -> Region, fldt: fn(t: t) -> t) -> substs { {self_r: substs.self_r.map(|r| fldr(*r)), @@ -1351,10 +1351,10 @@ fn fold_regions_and_ty( fn fold_regions( cx: ctxt, ty: t, - fldr: fn(r: region, in_fn: bool) -> region) -> t { + fldr: fn(r: Region, in_fn: bool) -> Region) -> t { fn do_fold(cx: ctxt, ty: t, in_fn: bool, - fldr: fn(region, bool) -> region) -> t { + fldr: fn(Region, bool) -> Region) -> t { if !type_has_regions(ty) { return ty; } fold_regions_and_ty( cx, ty, @@ -1365,9 +1365,9 @@ fn fold_regions( do_fold(cx, ty, false, fldr) } -fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t { +fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t { fn do_fold(cx: ctxt, t0: t, under_r: bool, - fldop: fn(region, bool) -> region) -> t { + fldop: fn(Region, bool) -> Region) -> t { let tb = get(t0); if !tbox_has_flag(tb, has_regions) { return t0; } match tb.sty { @@ -1777,7 +1777,7 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t, return needs_unwind_cleanup; } -enum kind { kind_(u32) } +enum Kind { kind_(u32) } /// can be copied (implicitly or explicitly) const KIND_MASK_COPY : u32 = 0b000000000000000000000000001_u32; @@ -1797,92 +1797,92 @@ const KIND_MASK_IMPLICIT : u32 = 0b000000000000000000000010000_u32; /// safe for default mode (subset of KIND_MASK_IMPLICIT) const KIND_MASK_DEFAULT_MODE : u32 = 0b000000000000000000000100000_u32; -fn kind_noncopyable() -> kind { +fn kind_noncopyable() -> Kind { kind_(0u32) } -fn kind_copyable() -> kind { +fn kind_copyable() -> Kind { kind_(KIND_MASK_COPY) } -fn kind_implicitly_copyable() -> kind { +fn kind_implicitly_copyable() -> Kind { kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY) } -fn kind_safe_for_default_mode() -> kind { +fn kind_safe_for_default_mode() -> Kind { // similar to implicit copy, but always includes vectors and strings kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY) } -fn kind_implicitly_sendable() -> kind { +fn kind_implicitly_sendable() -> Kind { kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_SEND) } -fn kind_safe_for_default_mode_send() -> kind { +fn kind_safe_for_default_mode_send() -> Kind { // similar to implicit copy, but always includes vectors and strings kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_SEND) } -fn kind_send_copy() -> kind { +fn kind_send_copy() -> Kind { kind_(KIND_MASK_COPY | KIND_MASK_SEND) } -fn kind_send_only() -> kind { +fn kind_send_only() -> Kind { kind_(KIND_MASK_SEND) } -fn kind_const() -> kind { +fn kind_const() -> Kind { kind_(KIND_MASK_CONST) } -fn kind_owned() -> kind { +fn kind_owned() -> Kind { kind_(KIND_MASK_OWNED) } -fn kind_top() -> kind { +fn kind_top() -> Kind { kind_(0xffffffffu32) } -fn remove_const(k: kind) -> kind { +fn remove_const(k: Kind) -> Kind { k - kind_const() } -fn remove_implicit(k: kind) -> kind { +fn remove_implicit(k: Kind) -> Kind { k - kind_(KIND_MASK_IMPLICIT | KIND_MASK_DEFAULT_MODE) } -fn remove_send(k: kind) -> kind { +fn remove_send(k: Kind) -> Kind { k - kind_(KIND_MASK_SEND) } -fn remove_owned_send(k: kind) -> kind { +fn remove_owned_send(k: Kind) -> Kind { k - kind_(KIND_MASK_OWNED) - kind_(KIND_MASK_SEND) } -fn remove_copyable(k: kind) -> kind { +fn remove_copyable(k: Kind) -> Kind { k - kind_(KIND_MASK_COPY | KIND_MASK_DEFAULT_MODE) } -impl kind : ops::BitAnd { - pure fn bitand(other: &kind) -> kind { +impl Kind : ops::BitAnd { + pure fn bitand(other: &Kind) -> Kind { unsafe { lower_kind(self, (*other)) } } } -impl kind : ops::BitOr { - pure fn bitor(other: &kind) -> kind { +impl Kind : ops::BitOr { + pure fn bitor(other: &Kind) -> Kind { unsafe { raise_kind(self, (*other)) } } } -impl kind : ops::Sub { - pure fn sub(other: &kind) -> kind { +impl Kind : ops::Sub { + pure fn sub(other: &Kind) -> Kind { unsafe { kind_(*self & !*(*other)) } @@ -1892,27 +1892,27 @@ impl kind : ops::Sub { // Using these query functions is preferable to direct comparison or matching // against the kind constants, as we may modify the kind hierarchy in the // future. -pure fn kind_can_be_implicitly_copied(k: kind) -> bool { +pure fn kind_can_be_implicitly_copied(k: Kind) -> bool { *k & KIND_MASK_IMPLICIT == KIND_MASK_IMPLICIT } -pure fn kind_is_safe_for_default_mode(k: kind) -> bool { +pure fn kind_is_safe_for_default_mode(k: Kind) -> bool { *k & KIND_MASK_DEFAULT_MODE == KIND_MASK_DEFAULT_MODE } -pure fn kind_can_be_copied(k: kind) -> bool { +pure fn kind_can_be_copied(k: Kind) -> bool { *k & KIND_MASK_COPY == KIND_MASK_COPY } -pure fn kind_can_be_sent(k: kind) -> bool { +pure fn kind_can_be_sent(k: Kind) -> bool { *k & KIND_MASK_SEND == KIND_MASK_SEND } -pure fn kind_is_owned(k: kind) -> bool { +pure fn kind_is_owned(k: Kind) -> bool { *k & KIND_MASK_OWNED == KIND_MASK_OWNED } -fn meta_kind(p: FnMeta) -> kind { +fn meta_kind(p: FnMeta) -> Kind { match p.proto { // XXX consider the kind bounds! proto_vstore(vstore_slice(_)) => kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE), @@ -1927,15 +1927,15 @@ fn meta_kind(p: FnMeta) -> kind { } } -fn kind_lteq(a: kind, b: kind) -> bool { +fn kind_lteq(a: Kind, b: Kind) -> bool { *a & *b == *a } -fn lower_kind(a: kind, b: kind) -> kind { +fn lower_kind(a: Kind, b: Kind) -> Kind { kind_(*a & *b) } -fn raise_kind(a: kind, b: kind) -> kind { +fn raise_kind(a: Kind, b: Kind) -> Kind { kind_(*a | *b) } @@ -1960,7 +1960,7 @@ fn test_kinds() { // with the given mutability can have. // This is used to prevent objects containing mutable state from being // implicitly copied and to compute whether things have const kind. -fn mutability_kind(m: mutability) -> kind { +fn mutability_kind(m: mutability) -> Kind { match (m) { m_mutbl => remove_const(remove_implicit(kind_top())), m_const => remove_implicit(kind_top()), @@ -1968,11 +1968,11 @@ fn mutability_kind(m: mutability) -> kind { } } -fn mutable_type_kind(cx: ctxt, ty: mt) -> kind { +fn mutable_type_kind(cx: ctxt, ty: mt) -> Kind { lower_kind(mutability_kind(ty.mutbl), type_kind(cx, ty.ty)) } -fn type_kind(cx: ctxt, ty: t) -> kind { +fn type_kind(cx: ctxt, ty: t) -> Kind { match cx.kind_cache.find(ty) { Some(result) => return result, None => {/* fall through */ } @@ -2550,7 +2550,7 @@ impl bound_region : to_bytes::IterBytes { } } -impl region : to_bytes::IterBytes { +impl Region : to_bytes::IterBytes { pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { match self { re_bound(ref br) => @@ -2763,7 +2763,7 @@ fn is_fn_ty(fty: t) -> bool { } } -fn ty_region(ty: t) -> region { +fn ty_region(ty: t) -> Region { match get(ty).sty { ty_rptr(r, _) => r, s => fail fmt!("ty_region() invoked on non-rptr: %?", s) @@ -4084,8 +4084,8 @@ impl RegionVid : cmp::Eq { pure fn ne(other: &RegionVid) -> bool { *self != *(*other) } } -impl region : cmp::Eq { - pure fn eq(other: ®ion) -> bool { +impl Region : cmp::Eq { + pure fn eq(other: &Region) -> bool { match self { re_bound(e0a) => { match (*other) { @@ -4119,7 +4119,7 @@ impl region : cmp::Eq { } } } - pure fn ne(other: ®ion) -> bool { !self.eq(other) } + pure fn ne(other: &Region) -> bool { !self.eq(other) } } impl bound_region : cmp::Eq { @@ -4367,9 +4367,9 @@ impl param_bound : cmp::Eq { pure fn ne(other: ¶m_bound) -> bool { !self.eq(other) } } -impl kind : cmp::Eq { - pure fn eq(other: &kind) -> bool { *self == *(*other) } - pure fn ne(other: &kind) -> bool { *self != *(*other) } +impl Kind : cmp::Eq { + pure fn eq(other: &Kind) -> bool { *self == *(*other) } + pure fn ne(other: &Kind) -> bool { *self != *(*other) } } diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 077d34700b8d..8d10343d78ee 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -46,7 +46,6 @@ use syntax::ast_map::node_id_to_str; use syntax::ast_util::{local_def, respan, split_trait_methods}; use syntax::visit; use metadata::csearch; -use driver::session::session; use util::common::may_break; use syntax::codemap::span; use pat_util::{pat_is_variant, pat_id_map, PatIdMap}; diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index 389c1adb016b..b8ff637f7dd3 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -58,7 +58,7 @@ trait ast_conv { fn get_region_reporting_err(tcx: ty::ctxt, span: span, - res: Result) -> ty::region { + res: Result) -> ty::Region { match res { result::Ok(r) => r, @@ -70,7 +70,7 @@ fn get_region_reporting_err(tcx: ty::ctxt, } fn ast_region_to_region( - self: AC, rscope: RS, span: span, a_r: @ast::region) -> ty::region { + self: AC, rscope: RS, span: span, a_r: @ast::region) -> ty::Region { let res = match a_r.node { ast::re_static => Ok(ty::re_static), @@ -155,7 +155,7 @@ const NO_TPS: uint = 2u; // internal notion of a type. `getter` is a function that returns the type // corresponding to a definition ID: fn ast_ty_to_ty( - self: AC, rscope: RS, &&ast_ty: @ast::ty) -> ty::t { + self: AC, rscope: RS, &&ast_ty: @ast::Ty) -> ty::t { fn ast_mt_to_mt( self: AC, rscope: RS, mt: ast::mt) -> ty::mt { diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 9a7f2192cb14..6de249ebc68f 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -166,20 +166,20 @@ fn blank_fn_ctxt(ccx: @crate_ctxt, rty: ty::t, } // a list of mapping from in-scope-region-names ("isr") to the -// corresponding ty::region -type isr_alist = @List<(ty::bound_region, ty::region)>; +// corresponding ty::Region +type isr_alist = @List<(ty::bound_region, ty::Region)>; trait get_and_find_region { - fn get(br: ty::bound_region) -> ty::region; - fn find(br: ty::bound_region) -> Option; + fn get(br: ty::bound_region) -> ty::Region; + fn find(br: ty::bound_region) -> Option; } impl isr_alist: get_and_find_region { - fn get(br: ty::bound_region) -> ty::region { + fn get(br: ty::bound_region) -> ty::Region { self.find(br).get() } - fn find(br: ty::bound_region) -> Option { + fn find(br: ty::bound_region) -> Option { for list::each(self) |isr| { let (isr_br, isr_r) = *isr; if isr_br == br { return Some(isr_r); } @@ -563,7 +563,7 @@ impl @fn_ctxt: ast_conv { impl @fn_ctxt { fn search_in_scope_regions(br: ty::bound_region) - -> Result + -> Result { match self.in_scope_regions.find(br) { Some(r) => result::Ok(r), @@ -581,13 +581,13 @@ impl @fn_ctxt { } impl @fn_ctxt: region_scope { - fn anon_region(span: span) -> Result { + fn anon_region(span: span) -> Result { result::Ok(self.infcx().next_region_var_nb(span)) } - fn self_region(_span: span) -> Result { + fn self_region(_span: span) -> Result { self.search_in_scope_regions(ty::br_self) } - fn named_region(_span: span, id: ast::ident) -> Result { + fn named_region(_span: span, id: ast::ident) -> Result { self.search_in_scope_regions(ty::br_named(id)) } } @@ -600,7 +600,7 @@ impl @fn_ctxt { pprust::expr_to_str(expr, self.tcx().sess.intr())) } - fn block_region() -> ty::region { + fn block_region() -> ty::Region { ty::re_scope(self.region_lb) } @@ -645,7 +645,7 @@ impl @fn_ctxt { self.write_ty(node_id, ty::mk_bot(self.tcx())); } - fn to_ty(ast_t: @ast::ty) -> ty::t { + fn to_ty(ast_t: @ast::Ty) -> ty::t { ast_ty_to_ty(self, self, ast_t) } @@ -736,7 +736,7 @@ impl @fn_ctxt { } fn mk_subr(a_is_expected: bool, span: span, - sub: ty::region, sup: ty::region) -> Result<(), ty::type_err> { + sub: ty::Region, sup: ty::Region) -> Result<(), ty::type_err> { infer::mk_subr(self.infcx(), a_is_expected, span, sub, sup) } @@ -760,8 +760,8 @@ impl @fn_ctxt { fn region_var_if_parameterized(rp: Option, span: span, - lower_bound: ty::region) - -> Option + lower_bound: ty::Region) + -> Option { rp.map( |_rp| self.infcx().next_region_var_with_lb(span, lower_bound)) @@ -1359,7 +1359,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Check field access expressions fn check_field(fcx: @fn_ctxt, expr: @ast::expr, is_callee: bool, - base: @ast::expr, field: ast::ident, tys: ~[@ast::ty]) + base: @ast::expr, field: ast::ident, tys: ~[@ast::Ty]) -> bool { let tcx = fcx.ccx.tcx; @@ -2443,7 +2443,7 @@ fn instantiate_path(fcx: @fn_ctxt, tpt: ty_param_bounds_and_ty, span: span, node_id: ast::node_id, - region_lb: ty::region) { + region_lb: ty::Region) { let ty_param_count = vec::len(*tpt.bounds); let ty_substs_len = vec::len(pth.types); diff --git a/src/rustc/middle/typeck/check/alt.rs b/src/rustc/middle/typeck/check/alt.rs index 24bcc2281fb9..caace6051982 100644 --- a/src/rustc/middle/typeck/check/alt.rs +++ b/src/rustc/middle/typeck/check/alt.rs @@ -112,8 +112,8 @@ fn check_legality_of_move_bindings(fcx: @fn_ctxt, type pat_ctxt = { fcx: @fn_ctxt, map: PatIdMap, - alt_region: ty::region, // Region for the alt as a whole - block_region: ty::region, // Region for the block of the arm + alt_region: ty::Region, // Region for the alt as a whole + block_region: ty::Region, // Region for the block of the arm }; fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index 04be00475482..eaf1a45afa9c 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -654,7 +654,7 @@ impl LookupContext { kind: AutoRefKind, autoderefs: uint, mutbls: &[ast::mutability], - mk_autoref_ty: &fn(ast::mutability, ty::region) -> ty::t) + mk_autoref_ty: &fn(ast::mutability, ty::Region) -> ty::t) -> Option { // This is hokey. We should have mutability inference as a @@ -930,7 +930,7 @@ impl LookupContext { } fn transform_self_type_for_method(tcx: ty::ctxt, - self_region: Option, + self_region: Option, impl_ty: ty::t, self_type: ast::self_ty_) -> ty::t diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs index 0b258da5672d..932cdd994da7 100644 --- a/src/rustc/middle/typeck/check/regionck.rs +++ b/src/rustc/middle/typeck/check/regionck.rs @@ -32,7 +32,7 @@ use middle::ty::{vstore_uniq}; enum rcx { rcx_({fcx: @fn_ctxt, mut errors_reported: uint}) } type rvt = visit::vt<@rcx>; -fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::region { +fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::Region { let tcx = fcx.tcx(); match def { def_local(node_id, _) | def_arg(node_id, _) | def_self(node_id) | @@ -335,7 +335,7 @@ fn constrain_auto_ref( fn constrain_free_variables( rcx: @rcx, - region: ty::region, + region: ty::Region, expr: @ast::expr) { /*! @@ -373,7 +373,7 @@ fn constrain_free_variables( fn constrain_regions_in_type_of_node( rcx: @rcx, id: ast::node_id, - encl_region: ty::region, + encl_region: ty::Region, span: span) -> bool { let tcx = rcx.fcx.tcx(); @@ -395,7 +395,7 @@ fn constrain_regions_in_type_of_node( fn constrain_regions_in_type( rcx: @rcx, - encl_region: ty::region, + encl_region: ty::Region, span: span, ty: ty::t) -> bool { @@ -417,9 +417,9 @@ fn constrain_regions_in_type( return (e == rcx.errors_reported); fn constrain_region(rcx: @rcx, - encl_region: ty::region, + encl_region: ty::Region, span: span, - region: ty::region) { + region: ty::Region) { let tcx = rcx.fcx.ccx.tcx; debug!("constrain_region(encl_region=%?, region=%?)", diff --git a/src/rustc/middle/typeck/check/regionmanip.rs b/src/rustc/middle/typeck/check/regionmanip.rs index 4afb3ad78a63..806b234540cd 100644 --- a/src/rustc/middle/typeck/check/regionmanip.rs +++ b/src/rustc/middle/typeck/check/regionmanip.rs @@ -10,7 +10,7 @@ fn replace_bound_regions_in_fn_ty( isr: isr_alist, self_info: Option, fn_ty: &ty::FnTy, - mapf: fn(ty::bound_region) -> ty::region) -> + mapf: fn(ty::bound_region) -> ty::Region) -> {isr: isr_alist, self_info: Option, fn_ty: ty::FnTy} { // Take self_info apart; the self_ty part is the only one we want @@ -83,7 +83,7 @@ fn replace_bound_regions_in_fn_ty( tcx: ty::ctxt, isr: isr_alist, tys: ~[ty::t], - to_r: fn(ty::bound_region) -> ty::region) -> isr_alist { + to_r: fn(ty::bound_region) -> ty::Region) -> isr_alist { // Takes `isr` (described above), `to_r` (described above), // and `r`, a region. If `r` is anything other than a bound @@ -93,8 +93,8 @@ fn replace_bound_regions_in_fn_ty( // updated isr_alist that now contains a mapping from `r` to // the result of calling `to_r` on it. fn append_isr(isr: isr_alist, - to_r: fn(ty::bound_region) -> ty::region, - r: ty::region) -> isr_alist { + to_r: fn(ty::bound_region) -> ty::Region, + r: ty::Region) -> isr_alist { match r { ty::re_free(_, _) | ty::re_static | ty::re_scope(_) | ty::re_var(_) => { diff --git a/src/rustc/middle/typeck/coherence.rs b/src/rustc/middle/typeck/coherence.rs index 9a9a8dda6e4d..189e7377d9c3 100644 --- a/src/rustc/middle/typeck/coherence.rs +++ b/src/rustc/middle/typeck/coherence.rs @@ -6,7 +6,7 @@ use metadata::csearch::{ProvidedTraitMethodInfo, each_path, get_impl_traits}; use metadata::csearch::{get_impls_for_mod}; -use metadata::cstore::{cstore, iter_crate_data}; +use metadata::cstore::{CStore, iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use middle::resolve::{Impl, MethodInfo}; use middle::ty::{ProvidedMethodSource, get, lookup_item_type, subst, t}; @@ -595,7 +595,7 @@ impl CoherenceChecker { fn create_impl_from_item(item: @item) -> @Impl { fn add_provided_methods(all_methods: &mut ~[@MethodInfo], all_provided_methods: ~[@ProvidedMethodInfo], - sess: driver::session::session) { + sess: driver::session::Session) { for all_provided_methods.each |provided_method| { debug!( "(creating impl) adding provided method `%s` to impl", @@ -694,7 +694,7 @@ impl CoherenceChecker { // External crate handling fn add_impls_for_module(impls_seen: HashMap, - crate_store: cstore, + crate_store: CStore, module_def_id: def_id) { let implementations = get_impls_for_mod(crate_store, diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 9e51225f172f..a5390d8f293a 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -76,7 +76,7 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) { impl @crate_ctxt { fn to_ty( - rs: RS, ast_ty: @ast::ty) -> ty::t { + rs: RS, ast_ty: @ast::Ty) -> ty::t { ast_ty_to_ty(self, rs, ast_ty) } @@ -345,7 +345,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, // Replaces bound references to the self region with `with_r`. fn replace_bound_self(tcx: ty::ctxt, ty: ty::t, - with_r: ty::region) -> ty::t { + with_r: ty::Region) -> ty::t { do ty::fold_regions(tcx, ty) |r, _in_fn| { if r == ty::re_bound(ty::br_self) {with_r} else {r} } diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs index 96849bf918d4..e0465b22c931 100644 --- a/src/rustc/middle/typeck/infer.rs +++ b/src/rustc/middle/typeck/infer.rs @@ -258,7 +258,6 @@ use util::ppaux::{ty_to_str, mt_to_str}; use result::{Result, Ok, Err, map_vec, map_vec2, iter_vec2}; use ty::{mk_fn, type_is_bot}; use check::regionmanip::{replace_bound_regions_in_fn_ty}; -use driver::session::session; use util::common::{indent, indenter}; use ast::{unsafe_fn, impure_fn, pure_fn, extern_fn}; use ast::{m_const, m_imm, m_mutbl}; @@ -275,7 +274,7 @@ use unify::{vals_and_bindings, root}; use integral::{int_ty_set, int_ty_set_all}; use combine::{combine_fields, eq_tys}; use assignment::Assign; -use to_str::to_str; +use to_str::ToStr; use sub::Sub; use lub::Lub; @@ -385,7 +384,7 @@ fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { } fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span, - a: ty::region, b: ty::region) -> ures { + a: ty::Region, b: ty::Region) -> ures { debug!("mk_subr(%s <: %s)", a.to_str(cx), b.to_str(cx)); do indent { do cx.commit { @@ -431,8 +430,8 @@ fn resolve_type(cx: infer_ctxt, a: ty::t, modes: uint) resolver(cx, modes).resolve_type_chk(a) } -fn resolve_region(cx: infer_ctxt, r: ty::region, modes: uint) - -> fres { +fn resolve_region(cx: infer_ctxt, r: ty::Region, modes: uint) + -> fres { resolver(cx, modes).resolve_region_chk(r) } @@ -628,12 +627,12 @@ impl infer_ctxt { ty::mk_int_var(self.tcx, self.next_int_var_id()) } - fn next_region_var_nb(span: span) -> ty::region { + fn next_region_var_nb(span: span) -> ty::Region { ty::re_var(self.region_vars.new_region_var(span)) } fn next_region_var_with_lb(span: span, - lb_region: ty::region) -> ty::region { + lb_region: ty::Region) -> ty::Region { let region_var = self.next_region_var_nb(span); // add lb_region as a lower bound on the newly built variable @@ -644,7 +643,7 @@ impl infer_ctxt { return region_var; } - fn next_region_var(span: span, scope_id: ast::node_id) -> ty::region { + fn next_region_var(span: span, scope_id: ast::node_id) -> ty::Region { self.next_region_var_with_lb(span, ty::re_scope(scope_id)) } diff --git a/src/rustc/middle/typeck/infer/assignment.rs b/src/rustc/middle/typeck/infer/assignment.rs index 53731551df57..a5af58904dd7 100644 --- a/src/rustc/middle/typeck/infer/assignment.rs +++ b/src/rustc/middle/typeck/infer/assignment.rs @@ -48,7 +48,7 @@ // A. But this upper-bound might be stricter than what is truly // needed. -use to_str::to_str; +use to_str::ToStr; use combine::combine_fields; fn to_ares(+c: cres) -> ares { @@ -190,7 +190,7 @@ priv impl Assign { a: ty::t, nr_b: ty::t, m: ast::mutability, - r_b: ty::region) -> ares { + r_b: ty::Region) -> ares { debug!("try_assign(a=%s, nr_b=%s, m=%?, r_b=%s)", a.to_str(self.infcx), diff --git a/src/rustc/middle/typeck/infer/combine.rs b/src/rustc/middle/typeck/infer/combine.rs index bdda45c1168a..342a2ce2b76c 100644 --- a/src/rustc/middle/typeck/infer/combine.rs +++ b/src/rustc/middle/typeck/infer/combine.rs @@ -44,7 +44,7 @@ // terms of error reporting, although we do not do that properly right // now. -use to_str::to_str; +use to_str::ToStr; use ty::{FnTyBase, FnMeta, FnSig}; trait combine { @@ -72,8 +72,8 @@ trait combine { fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres; fn ret_styles(r1: ret_style, r2: ret_style) -> cres; fn purities(a: purity, b: purity) -> cres; - fn contraregions(a: ty::region, b: ty::region) -> cres; - fn regions(a: ty::region, b: ty::region) -> cres; + fn contraregions(a: ty::Region, b: ty::Region) -> cres; + fn regions(a: ty::Region, b: ty::Region) -> cres; fn vstores(vk: ty::terr_vstore_kind, a: ty::vstore, b: ty::vstore) -> cres; } @@ -103,7 +103,7 @@ fn eq_tys(self: &C, a: ty::t, b: ty::t) -> ures { } } -fn eq_regions(self: &C, a: ty::region, b: ty::region) -> ures { +fn eq_regions(self: &C, a: ty::Region, b: ty::Region) -> ures { debug!("eq_regions(%s, %s)", a.to_str(self.infcx()), b.to_str(self.infcx())); @@ -127,8 +127,8 @@ fn eq_regions(self: &C, a: ty::region, b: ty::region) -> ures { fn eq_opt_regions( self: &C, - a: Option, - b: Option) -> cres> { + a: Option, + b: Option) -> cres> { match (a, b) { (None, None) => { @@ -160,9 +160,9 @@ fn super_substs( fn relate_region_param( self: &C, did: ast::def_id, - a: Option, - b: Option) - -> cres> + a: Option, + b: Option) + -> cres> { let polyty = ty::lookup_item_type(self.infcx().tcx, did); match (polyty.region_param, a, b) { diff --git a/src/rustc/middle/typeck/infer/glb.rs b/src/rustc/middle/typeck/infer/glb.rs index a8676a63b889..77e753fa2204 100644 --- a/src/rustc/middle/typeck/infer/glb.rs +++ b/src/rustc/middle/typeck/infer/glb.rs @@ -1,6 +1,6 @@ use combine::*; use lattice::*; -use to_str::to_str; +use to_str::ToStr; enum Glb = combine_fields; // "greatest lower bound" (common subtype) @@ -109,7 +109,7 @@ impl Glb: combine { } } - fn regions(a: ty::region, b: ty::region) -> cres { + fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%?, %?)", self.tag(), a.to_str(self.infcx), @@ -120,7 +120,7 @@ impl Glb: combine { } } - fn contraregions(a: ty::region, b: ty::region) -> cres { + fn contraregions(a: ty::Region, b: ty::Region) -> cres { Lub(*self).regions(a, b) } diff --git a/src/rustc/middle/typeck/infer/integral.rs b/src/rustc/middle/typeck/infer/integral.rs index 168709596dc4..1b23cb52b20c 100644 --- a/src/rustc/middle/typeck/infer/integral.rs +++ b/src/rustc/middle/typeck/infer/integral.rs @@ -4,7 +4,7 @@ Code related to integral type inference. */ -use to_str::to_str; +use to_str::ToStr; // Bitvector to represent sets of integral types enum int_ty_set = uint; diff --git a/src/rustc/middle/typeck/infer/lattice.rs b/src/rustc/middle/typeck/infer/lattice.rs index 04133cab9d76..699613e8ae65 100644 --- a/src/rustc/middle/typeck/infer/lattice.rs +++ b/src/rustc/middle/typeck/infer/lattice.rs @@ -1,6 +1,6 @@ use combine::*; use unify::*; -use to_str::to_str; +use to_str::ToStr; // ______________________________________________________________________ // Lattice operations on variables diff --git a/src/rustc/middle/typeck/infer/lub.rs b/src/rustc/middle/typeck/infer/lub.rs index 093da5caec87..dcff863a126f 100644 --- a/src/rustc/middle/typeck/infer/lub.rs +++ b/src/rustc/middle/typeck/infer/lub.rs @@ -1,6 +1,6 @@ use combine::*; use lattice::*; -use to_str::to_str; +use to_str::ToStr; enum Lub = combine_fields; // "subtype", "subregion" etc @@ -88,11 +88,11 @@ impl Lub: combine { } } - fn contraregions(a: ty::region, b: ty::region) -> cres { + fn contraregions(a: ty::Region, b: ty::Region) -> cres { return Glb(*self).regions(a, b); } - fn regions(a: ty::region, b: ty::region) -> cres { + fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%?, %?)", self.tag(), a.to_str(self.infcx), diff --git a/src/rustc/middle/typeck/infer/region_var_bindings.rs b/src/rustc/middle/typeck/infer/region_var_bindings.rs index 8bbdab74d230..86a872341f56 100644 --- a/src/rustc/middle/typeck/infer/region_var_bindings.rs +++ b/src/rustc/middle/typeck/infer/region_var_bindings.rs @@ -312,10 +312,10 @@ use std::map::HashMap; use std::cell::{Cell, empty_cell}; use std::list::{List, Nil, Cons}; -use ty::{region, RegionVid}; use region::is_subregion_of; +use ty::{Region, RegionVid}; use syntax::codemap; -use to_str::to_str; +use to_str::ToStr; use util::ppaux::note_and_explain_region; export RegionVarBindings; @@ -325,8 +325,8 @@ export glb_regions; enum Constraint { ConstrainVarSubVar(RegionVid, RegionVid), - ConstrainRegSubVar(region, RegionVid), - ConstrainVarSubReg(RegionVid, region) + ConstrainRegSubVar(Region, RegionVid), + ConstrainVarSubReg(RegionVid, Region) } impl Constraint : cmp::Eq { @@ -365,8 +365,8 @@ impl Constraint : to_bytes::IterBytes { } struct TwoRegions { - a: region, - b: region, + a: Region, + b: Region, } impl TwoRegions : cmp::Eq { @@ -394,7 +394,7 @@ type CombineMap = HashMap; struct RegionVarBindings { tcx: ty::ctxt, var_spans: DVec, - values: Cell<~[ty::region]>, + values: Cell<~[ty::Region]>, constraints: HashMap, lubs: CombineMap, glbs: CombineMap, @@ -501,7 +501,7 @@ impl RegionVarBindings { } } - fn make_subregion(span: span, sub: region, sup: region) -> cres<()> { + fn make_subregion(span: span, sub: Region, sup: Region) -> cres<()> { // cannot add constraints once regions are resolved assert self.values.is_empty(); @@ -529,7 +529,7 @@ impl RegionVarBindings { } } - fn lub_regions(span: span, a: region, b: region) -> cres { + fn lub_regions(span: span, a: Region, b: Region) -> cres { // cannot add constraints once regions are resolved assert self.values.is_empty(); @@ -551,7 +551,7 @@ impl RegionVarBindings { } } - fn glb_regions(span: span, a: region, b: region) -> cres { + fn glb_regions(span: span, a: Region, b: Region) -> cres { // cannot add constraints once regions are resolved assert self.values.is_empty(); @@ -574,7 +574,7 @@ impl RegionVarBindings { } } - fn resolve_var(rid: RegionVid) -> ty::region { + fn resolve_var(rid: RegionVid) -> ty::Region { debug!("RegionVarBindings: resolve_var(%?=%u)", rid, *rid); if self.values.is_empty() { self.tcx.sess.span_bug( @@ -586,9 +586,9 @@ impl RegionVarBindings { self.values.with_ref(|values| values[*rid]) } - fn combine_vars(combines: CombineMap, a: region, b: region, span: span, - relate: fn(old_r: region, new_r: region) -> cres<()>) - -> cres { + fn combine_vars(combines: CombineMap, a: Region, b: Region, span: span, + relate: fn(old_r: Region, new_r: Region) -> cres<()>) + -> cres { let vars = TwoRegions { a: a, b: b }; match combines.find(vars) { @@ -623,11 +623,11 @@ impl RegionVarBindings { } priv impl RegionVarBindings { - fn is_subregion_of(sub: region, sup: region) -> bool { + fn is_subregion_of(sub: Region, sup: Region) -> bool { is_subregion_of(self.tcx.region_map, sub, sup) } - fn lub_concrete_regions(+a: region, +b: region) -> region { + fn lub_concrete_regions(+a: Region, +b: Region) -> Region { match (a, b) { (ty::re_static, _) | (_, ty::re_static) => { ty::re_static // nothing lives longer than static @@ -682,7 +682,7 @@ priv impl RegionVarBindings { } } - fn glb_concrete_regions(+a: region, +b: region) -> cres { + fn glb_concrete_regions(+a: Region, +b: Region) -> cres { match (a, b) { (ty::re_static, r) | (r, ty::re_static) => { // static lives longer than everything else @@ -771,7 +771,7 @@ impl Classification : cmp::Eq { pure fn ne(other: &Classification) -> bool { !self.eq(other) } } -enum GraphNodeValue { NoValue, Value(region), ErrorValue } +enum GraphNodeValue { NoValue, Value(Region), ErrorValue } struct GraphNode { span: span, @@ -792,7 +792,7 @@ struct Graph { } struct SpannedRegion { - region: region, + region: Region, span: span, } @@ -803,7 +803,7 @@ fn TwoRegionsMap() -> TwoRegionsMap { } impl RegionVarBindings { - fn infer_variable_values() -> ~[region] { + fn infer_variable_values() -> ~[Region] { let graph = self.construct_graph(); self.expansion(&graph); self.contraction(&graph); @@ -895,7 +895,7 @@ impl RegionVarBindings { } } - fn expand_node(a_region: region, + fn expand_node(a_region: Region, b_vid: RegionVid, b_node: &GraphNode) -> bool { debug!("expand_node(%?, %? == %?)", @@ -955,7 +955,7 @@ impl RegionVarBindings { fn contract_node(a_vid: RegionVid, a_node: &GraphNode, - b_region: region) -> bool { + b_region: Region) -> bool { debug!("contract_node(%? == %?/%?, %?)", a_vid, a_node.value, a_node.classification, b_region); @@ -985,8 +985,8 @@ impl RegionVarBindings { fn check_node(self: &RegionVarBindings, a_vid: RegionVid, a_node: &GraphNode, - a_region: region, - b_region: region) -> bool { + a_region: Region, + b_region: Region) -> bool { if !self.is_subregion_of(a_region, b_region) { debug!("Setting %? to ErrorValue: %? not subregion of %?", a_vid, a_region, b_region); @@ -998,8 +998,8 @@ impl RegionVarBindings { fn adjust_node(self: &RegionVarBindings, a_vid: RegionVid, a_node: &GraphNode, - a_region: region, - b_region: region) -> bool { + a_region: Region, + b_region: Region) -> bool { match self.glb_concrete_regions(a_region, b_region) { Ok(glb) => { if glb == a_region { @@ -1040,7 +1040,7 @@ impl RegionVarBindings { debug!("---- %s Complete after %u iteration(s)", tag, iteration); } - fn extract_regions_and_report_errors(graph: &Graph) -> ~[region] { + fn extract_regions_and_report_errors(graph: &Graph) -> ~[Region] { let dup_map = TwoRegionsMap(); graph.nodes.mapi(|idx, node| { match node.value { @@ -1073,8 +1073,8 @@ impl RegionVarBindings { // Used to suppress reporting the same basic error over and over fn is_reported(dup_map: TwoRegionsMap, - r_a: region, - r_b: region) -> bool { + r_a: Region, + r_b: Region) -> bool { let key = TwoRegions { a: r_a, b: r_b }; !dup_map.insert(key, ()) } diff --git a/src/rustc/middle/typeck/infer/resolve.rs b/src/rustc/middle/typeck/infer/resolve.rs index 2a851a5f7bb2..5a55fbf9a5df 100644 --- a/src/rustc/middle/typeck/infer/resolve.rs +++ b/src/rustc/middle/typeck/infer/resolve.rs @@ -35,7 +35,7 @@ // probably better off writing `resolve_all - resolve_ivar`. use integral::*; -use to_str::to_str; +use to_str::ToStr; const resolve_nested_tvar: uint = 0b00000001; const resolve_rvar: uint = 0b00000010; @@ -98,7 +98,7 @@ impl resolve_state { } } - fn resolve_region_chk(orig: ty::region) -> fres { + fn resolve_region_chk(orig: ty::Region) -> fres { self.err = None; let resolved = indent(|| self.resolve_region(orig) ); match self.err { @@ -145,7 +145,7 @@ impl resolve_state { } } - fn resolve_region(orig: ty::region) -> ty::region { + fn resolve_region(orig: ty::Region) -> ty::Region { debug!("Resolve_region(%s)", orig.to_str(self.infcx)); match orig { ty::re_var(rid) => self.resolve_region_var(rid), @@ -153,14 +153,14 @@ impl resolve_state { } } - fn resolve_region_var(rid: RegionVid) -> ty::region { + fn resolve_region_var(rid: RegionVid) -> ty::Region { if !self.should(resolve_rvar) { return ty::re_var(rid) } self.infcx.region_vars.resolve_var(rid) } - fn assert_not_rvar(rid: RegionVid, r: ty::region) { + fn assert_not_rvar(rid: RegionVid, r: ty::Region) { match r { ty::re_var(rid2) => { self.err = Some(region_var_bound_by_region_var(rid, rid2)); diff --git a/src/rustc/middle/typeck/infer/sub.rs b/src/rustc/middle/typeck/infer/sub.rs index e6bcdf3e71ff..0aba993512bb 100644 --- a/src/rustc/middle/typeck/infer/sub.rs +++ b/src/rustc/middle/typeck/infer/sub.rs @@ -1,6 +1,6 @@ use combine::*; use unify::*; -use to_str::to_str; +use to_str::ToStr; enum Sub = combine_fields; // "subtype", "subregion" etc @@ -20,14 +20,14 @@ impl Sub: combine { Sub(opp).tys(b, a) } - fn contraregions(a: ty::region, b: ty::region) -> cres { + fn contraregions(a: ty::Region, b: ty::Region) -> cres { let opp = combine_fields { a_is_expected: !self.a_is_expected,.. *self }; Sub(opp).regions(b, a) } - fn regions(a: ty::region, b: ty::region) -> cres { + fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%s, %s)", self.tag(), a.to_str(self.infcx), diff --git a/src/rustc/middle/typeck/infer/to_str.rs b/src/rustc/middle/typeck/infer/to_str.rs index 7acfdcac424d..c98a217a7464 100644 --- a/src/rustc/middle/typeck/infer/to_str.rs +++ b/src/rustc/middle/typeck/infer/to_str.rs @@ -1,29 +1,29 @@ use integral::{int_ty_set}; use unify::{var_value, redirect, root}; -trait to_str { +trait ToStr { fn to_str(cx: infer_ctxt) -> ~str; } -impl ty::t: to_str { +impl ty::t: ToStr { fn to_str(cx: infer_ctxt) -> ~str { ty_to_str(cx.tcx, self) } } -impl ty::mt: to_str { +impl ty::mt: ToStr { fn to_str(cx: infer_ctxt) -> ~str { mt_to_str(cx.tcx, self) } } -impl ty::region: to_str { +impl ty::Region: ToStr { fn to_str(cx: infer_ctxt) -> ~str { util::ppaux::region_to_str(cx.tcx, self) } } -impl bound: to_str { +impl bound: ToStr { fn to_str(cx: infer_ctxt) -> ~str { match self { Some(v) => v.to_str(cx), @@ -32,7 +32,7 @@ impl bound: to_str { } } -impl bounds: to_str { +impl bounds: ToStr { fn to_str(cx: infer_ctxt) -> ~str { fmt!("{%s <: %s}", self.lb.to_str(cx), @@ -40,7 +40,7 @@ impl bounds: to_str { } } -impl int_ty_set: to_str { +impl int_ty_set: ToStr { fn to_str(_cx: infer_ctxt) -> ~str { match self { int_ty_set(v) => uint::to_str(v, 10u) @@ -48,7 +48,7 @@ impl int_ty_set: to_str { } } -impl var_value: to_str { +impl var_value: ToStr { fn to_str(cx: infer_ctxt) -> ~str { match self { redirect(vid) => fmt!("redirect(%s)", vid.to_str()), diff --git a/src/rustc/middle/typeck/infer/unify.rs b/src/rustc/middle/typeck/infer/unify.rs index 7ccbaa40ada1..f865705563c6 100644 --- a/src/rustc/middle/typeck/infer/unify.rs +++ b/src/rustc/middle/typeck/infer/unify.rs @@ -1,6 +1,6 @@ use combine::combine; use integral::*; -use to_str::to_str; +use to_str::ToStr; use std::smallintmap::SmallIntMap; enum var_value { @@ -46,7 +46,7 @@ impl infer_ctxt { } } - fn set( + fn set( vb: &vals_and_bindings, vid: V, +new_v: var_value) { diff --git a/src/rustc/middle/typeck/rscope.rs b/src/rustc/middle/typeck/rscope.rs index 9b9695088f37..d379607d6a81 100644 --- a/src/rustc/middle/typeck/rscope.rs +++ b/src/rustc/middle/typeck/rscope.rs @@ -2,21 +2,21 @@ use result::Result; use syntax::parse::token::special_idents; trait region_scope { - fn anon_region(span: span) -> Result; - fn self_region(span: span) -> Result; - fn named_region(span: span, id: ast::ident) -> Result; + fn anon_region(span: span) -> Result; + fn self_region(span: span) -> Result; + fn named_region(span: span, id: ast::ident) -> Result; } enum empty_rscope { empty_rscope } impl empty_rscope: region_scope { - fn anon_region(_span: span) -> Result { + fn anon_region(_span: span) -> Result { result::Ok(ty::re_static) } - fn self_region(_span: span) -> Result { + fn self_region(_span: span) -> Result { result::Err(~"only the static region is allowed here") } fn named_region(_span: span, _id: ast::ident) - -> Result + -> Result { result::Err(~"only the static region is allowed here") } @@ -24,17 +24,17 @@ impl empty_rscope: region_scope { enum type_rscope = Option; impl type_rscope: region_scope { - fn anon_region(_span: span) -> Result { + fn anon_region(_span: span) -> Result { match *self { Some(_) => result::Ok(ty::re_bound(ty::br_self)), None => result::Err(~"to use region types here, the containing \ type must be declared with a region bound") } } - fn self_region(span: span) -> Result { + fn self_region(span: span) -> Result { self.anon_region(span) } - fn named_region(span: span, id: ast::ident) -> Result { + fn named_region(span: span, id: ast::ident) -> Result { do empty_rscope.named_region(span, id).chain_err |_e| { result::Err(~"named regions other than `self` are not \ allowed as part of a type declaration") @@ -42,26 +42,26 @@ impl type_rscope: region_scope { } } -fn bound_self_region(rp: Option) -> Option { +fn bound_self_region(rp: Option) -> Option { match rp { Some(_) => Some(ty::re_bound(ty::br_self)), None => None } } -enum anon_rscope = {anon: ty::region, base: region_scope}; -fn in_anon_rscope(self: RS, r: ty::region) +enum anon_rscope = {anon: ty::Region, base: region_scope}; +fn in_anon_rscope(self: RS, r: ty::Region) -> @anon_rscope { @anon_rscope({anon: r, base: self as region_scope}) } impl @anon_rscope: region_scope { - fn anon_region(_span: span) -> Result { + fn anon_region(_span: span) -> Result { result::Ok(self.anon) } - fn self_region(span: span) -> Result { + fn self_region(span: span) -> Result { self.base.self_region(span) } - fn named_region(span: span, id: ast::ident) -> Result { + fn named_region(span: span, id: ast::ident) -> Result { self.base.named_region(span, id) } } @@ -76,15 +76,15 @@ fn in_binding_rscope(self: RS) @binding_rscope { base: base, anon_bindings: 0 } } impl @binding_rscope: region_scope { - fn anon_region(_span: span) -> Result { + fn anon_region(_span: span) -> Result { let idx = self.anon_bindings; self.anon_bindings += 1; result::Ok(ty::re_bound(ty::br_anon(idx))) } - fn self_region(span: span) -> Result { + fn self_region(span: span) -> Result { self.base.self_region(span) } - fn named_region(span: span, id: ast::ident) -> Result { + fn named_region(span: span, id: ast::ident) -> Result { do self.base.named_region(span, id).chain_err |_e| { result::Ok(ty::re_bound(ty::br_named(id))) } diff --git a/src/rustc/util/common.rs b/src/rustc/util/common.rs index e314a12a6765..0c6ec267da81 100644 --- a/src/rustc/util/common.rs +++ b/src/rustc/util/common.rs @@ -1,6 +1,5 @@ use std::map::HashMap; use syntax::ast; -use ast::{ty, pat}; use syntax::codemap::{span}; use syntax::visit; use syntax::print; diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index 3f8ca0f6e6a6..27ace283fa0c 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -6,7 +6,7 @@ use middle::ty::{bound_copy, bound_const, bound_owned, bound_send, use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid}; use middle::ty::{ck_block, ck_box, ck_uniq, ctxt, field, method}; use middle::ty::{mt, t, param_bound}; -use middle::ty::{re_bound, re_free, re_scope, re_var, re_static, region}; +use middle::ty::{re_bound, re_free, re_scope, re_var, re_static, Region}; use middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_enum}; use middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int}; use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param}; @@ -21,11 +21,10 @@ use syntax::print::pprust::{path_to_str, proto_to_str, mode_to_str, purity_to_str}; use syntax::{ast, ast_util}; use syntax::ast_map; -use driver::session::session; fn note_and_explain_region(cx: ctxt, prefix: ~str, - region: ty::region, + region: ty::Region, suffix: ~str) { match explain_region_and_span(cx, region) { (str, Some(span)) => { @@ -42,13 +41,13 @@ fn note_and_explain_region(cx: ctxt, /// Returns a string like "the block at 27:31" that attempts to explain a /// lifetime in a way it might plausibly be understood. -fn explain_region(cx: ctxt, region: ty::region) -> ~str { +fn explain_region(cx: ctxt, region: ty::Region) -> ~str { let (res, _) = explain_region_and_span(cx, region); return res; } -fn explain_region_and_span(cx: ctxt, region: ty::region) +fn explain_region_and_span(cx: ctxt, region: ty::Region) -> (~str, Option) { return match region { @@ -172,7 +171,7 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str { // In general, if you are giving a region error message, // you should use `explain_region()` or, better yet, // `note_and_explain_region()` -fn region_to_str(cx: ctxt, region: region) -> ~str { +fn region_to_str(cx: ctxt, region: Region) -> ~str { if cx.sess.verbose() { return fmt!("&%?", region); } @@ -381,7 +380,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { fn parameterized(cx: ctxt, base: ~str, - self_r: Option, + self_r: Option, tps: ~[ty::t]) -> ~str { let r_str = match self_r { diff --git a/src/rustdoc/astsrv.rs b/src/rustdoc/astsrv.rs index 27d4d51a010f..7b2c6fe5f0cb 100644 --- a/src/rustdoc/astsrv.rs +++ b/src/rustdoc/astsrv.rs @@ -10,7 +10,7 @@ non-sendableness. use std::map::HashMap; use rustc::driver::session; use session::{basic_options, options}; -use session::session; +use session::Session; use rustc::driver::driver; use syntax::diagnostic; use syntax::diagnostic::handler; @@ -35,7 +35,7 @@ type Ctxt = { type SrvOwner = fn(srv: Srv) -> T; type CtxtHandler = fn~(ctxt: Ctxt) -> T; -type Parser = fn~(session, ~str) -> @ast::crate; +type Parser = fn~(Session, ~str) -> @ast::crate; enum Msg { HandleRequest(fn~(Ctxt)), @@ -101,7 +101,7 @@ fn exec( comm::recv(po) } -fn build_ctxt(sess: session, +fn build_ctxt(sess: Session, ast: @ast::crate) -> Ctxt { use rustc::front::config; @@ -118,7 +118,7 @@ fn build_ctxt(sess: session, } } -fn build_session() -> session { +fn build_session() -> Session { let sopts: @options = basic_options(); let codemap = codemap::new_codemap(); let error_handlers = build_error_handlers(codemap); @@ -137,7 +137,7 @@ type ErrorHandlers = { // Build a custom error handler that will allow us to ignore non-fatal // errors fn build_error_handlers( - codemap: codemap::codemap + codemap: codemap::CodeMap ) -> ErrorHandlers { type DiagnosticHandler = { @@ -156,13 +156,13 @@ fn build_error_handlers( fn note(msg: &str) { self.inner.note(msg) } fn bug(msg: &str) -> ! { self.inner.bug(msg) } fn unimpl(msg: &str) -> ! { self.inner.unimpl(msg) } - fn emit(cmsp: Option<(codemap::codemap, codemap::span)>, + fn emit(cmsp: Option<(codemap::CodeMap, codemap::span)>, msg: &str, lvl: diagnostic::level) { self.inner.emit(cmsp, msg, lvl) } } - let emitter = fn@(cmsp: Option<(codemap::codemap, codemap::span)>, + let emitter = fn@(cmsp: Option<(codemap::CodeMap, codemap::span)>, msg: &str, lvl: diagnostic::level) { diagnostic::emit(cmsp, msg, lvl); }; diff --git a/src/rustdoc/parse.rs b/src/rustdoc/parse.rs index 59d64f18d59a..7fc17dfe8386 100644 --- a/src/rustdoc/parse.rs +++ b/src/rustdoc/parse.rs @@ -20,16 +20,16 @@ fn from_str(source: ~str) -> @ast::crate { ~"-", @source, ~[], parse::new_parse_sess(None)) } -fn from_file_sess(sess: session::session, file: &Path) -> @ast::crate { +fn from_file_sess(sess: session::Session, file: &Path) -> @ast::crate { parse::parse_crate_from_file( file, cfg(sess, file_input(*file)), sess.parse_sess) } -fn from_str_sess(sess: session::session, source: ~str) -> @ast::crate { +fn from_str_sess(sess: session::Session, source: ~str) -> @ast::crate { parse::parse_crate_from_source_str( ~"-", @source, cfg(sess, str_input(source)), sess.parse_sess) } -fn cfg(sess: session::session, input: driver::input) -> ast::crate_cfg { +fn cfg(sess: session::Session, input: driver::input) -> ast::crate_cfg { driver::default_configuration(sess, ~"rustdoc", input) } diff --git a/src/test/run-pass/issue-2930.rs b/src/test/run-pass/issue-2930.rs index c480d382adc0..bccaeeaf18dd 100644 --- a/src/test/run-pass/issue-2930.rs +++ b/src/test/run-pass/issue-2930.rs @@ -1,6 +1,6 @@ proto! stream ( - stream:send { - send(T) -> stream + Stream:send { + send(T) -> Stream } ) diff --git a/src/test/run-pass/pipe-select.rs b/src/test/run-pass/pipe-select.rs index 627cdbee9cab..23588de2ecaf 100644 --- a/src/test/run-pass/pipe-select.rs +++ b/src/test/run-pass/pipe-select.rs @@ -14,8 +14,8 @@ proto! oneshot ( ) proto! stream ( - stream:send { - send(T) -> stream + Stream:send { + send(T) -> Stream } ) From 7d845056540237e54bf8f02ab8f5e477f71a7edd Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 15:29:45 -0700 Subject: [PATCH 208/292] Error out in resolve if structs try to capture type parameters Closes #3214 --- src/rustc/middle/resolve.rs | 4 ++-- src/test/compile-fail/issue-3214.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 81ea6daf1958..6f7230fe4c1a 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -3522,8 +3522,8 @@ impl Resolver { let outer_type_parameter_count = (*type_parameters).len(); let borrowed_type_parameters: &~[ty_param] = &*type_parameters; do self.with_type_parameter_rib(HasTypeParameters - (borrowed_type_parameters, id, 0u, - NormalRibKind)) { + (borrowed_type_parameters, id, 0, + OpaqueFunctionRibKind)) { // Resolve the type parameters. self.resolve_type_parameters(*type_parameters, visitor); diff --git a/src/test/compile-fail/issue-3214.rs b/src/test/compile-fail/issue-3214.rs index 3c783b99232d..7008f8c4ce29 100644 --- a/src/test/compile-fail/issue-3214.rs +++ b/src/test/compile-fail/issue-3214.rs @@ -1,7 +1,7 @@ -// xfail-test fn foo() { struct foo { - mut x: T, //~ ERROR quux + mut x: T, //~ ERROR attempt to use a type argument out of scope + //~^ ERROR use of undeclared type name drop { } } } From d29328617da4704063fca25792bda6811e18ad1b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 17:09:05 -0700 Subject: [PATCH 209/292] Add test case for Issue 2895 --- src/test/run-pass/issue-2895.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/test/run-pass/issue-2895.rs diff --git a/src/test/run-pass/issue-2895.rs b/src/test/run-pass/issue-2895.rs new file mode 100644 index 000000000000..b51e6360e524 --- /dev/null +++ b/src/test/run-pass/issue-2895.rs @@ -0,0 +1,16 @@ +use sys::size_of; +extern mod std; + +struct Cat { + x: int +} + +struct Kitty { + x: int, + drop {} +} + +fn main() { + assert (size_of::() == 8 as uint); + assert (size_of::() == 16 as uint); +} From bbc46d527d70ac0bcab6c2b0763f059efc27a142 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 17:12:42 -0700 Subject: [PATCH 210/292] Add test for Issue 2823 --- src/test/compile-fail/issue-2823.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/compile-fail/issue-2823.rs diff --git a/src/test/compile-fail/issue-2823.rs b/src/test/compile-fail/issue-2823.rs new file mode 100644 index 000000000000..fd2c17584581 --- /dev/null +++ b/src/test/compile-fail/issue-2823.rs @@ -0,0 +1,12 @@ +struct C { + x: int, + drop { + #error("dropping: %?", self.x); + } +} + +fn main() { + let c = C{ x: 2}; + let d = copy c; //~ ERROR copying a noncopyable value + #error("%?", d.x); +} \ No newline at end of file From b38092e9a2b5965ab8b8e73580e4d39ed701330a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Oct 2012 17:18:45 -0700 Subject: [PATCH 211/292] In ty::normalize_ty, don't replace self_regions with None Instead, replace with re_static. This was causing ty::subst to fail when called from trans::type_of::type_of. Already discussed with nmatsakis and it's a small change, so no review. Closes #3447 --- src/rustc/middle/ty.rs | 14 ++++++++++---- src/test/run-pass/issue-3447.rs | 5 ++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 84510c7161e3..90527e88bc85 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -1473,7 +1473,10 @@ fn subst(cx: ctxt, fold_regions_and_ty( cx, typ, |r| match r { - re_bound(br_self) => substs.self_r.get(), + re_bound(br_self) => substs.self_r.expect( + #fmt("ty::subst: \ + Reference to self region when given substs with no \ + self region, ty = %s", ty_to_str(cx, typ))), _ => r }, |t| do_subst(cx, substs, t), @@ -3910,9 +3913,11 @@ fn normalize_ty(cx: ctxt, t: t) -> t { ty_enum(did, r) => match r.self_r { Some(_) => - // This enum has a self region. Get rid of it + // Use re_static since trans doesn't care about regions mk_enum(cx, did, - {self_r: None, self_ty: None, tps: r.tps}), + {self_r: Some(ty::re_static), + self_ty: None, + tps: r.tps}), None => t }, @@ -3921,7 +3926,8 @@ fn normalize_ty(cx: ctxt, t: t) -> t { match r.self_r { Some(_) => // Ditto. - mk_class(cx, did, {self_r: None, self_ty: None, tps: r.tps}), + mk_class(cx, did, {self_r: Some(ty::re_static), self_ty: None, + tps: r.tps}), None => t }, diff --git a/src/test/run-pass/issue-3447.rs b/src/test/run-pass/issue-3447.rs index fab92ea6dcad..7302163a312c 100644 --- a/src/test/run-pass/issue-3447.rs +++ b/src/test/run-pass/issue-3447.rs @@ -1,4 +1,3 @@ -// xfail-test struct list { element: &self/T, mut next: Option<@list> @@ -11,13 +10,13 @@ impl list{ next: option::None }; - self.next = Some(@newList); + self.next = Some(@(move newList)); } } fn main() { let s = @"str"; - let ls: list<@str> = list { + let ls = list { element: &s, next: option::None }; From 4dc67c5e6af76eab83b93e5b494d3073d78229db Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 15 Oct 2012 18:04:15 -0700 Subject: [PATCH 212/292] rustc: Implement intra-crate static methods on anonymous trait implementations. --- src/rustc/middle/resolve.rs | 406 +++++++++++++----- src/test/run-pass/anon-trait-static-method.rs | 15 + 2 files changed, 312 insertions(+), 109 deletions(-) create mode 100644 src/test/run-pass/anon-trait-static-method.rs diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 6f7230fe4c1a..f522cca7a995 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -9,9 +9,8 @@ use syntax::ast::{_mod, add, arm}; use syntax::ast::{bind_by_ref, bind_by_implicit_ref, bind_by_value}; use syntax::ast::{bitand, bitor, bitxor}; use syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send}; -use syntax::ast::{bound_trait, binding_mode, - capture_clause, class_ctor, class_dtor}; -use syntax::ast::{crate, crate_num, decl_item}; +use syntax::ast::{bound_trait, binding_mode, capture_clause, class_ctor}; +use syntax::ast::{class_dtor, crate, crate_num, decl_item}; use syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn}; use syntax::ast::{def_foreign_mod, def_id, def_label, def_local, def_mod}; use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param}; @@ -294,6 +293,35 @@ enum EnumVariantOrConstResolution { EnumVariantOrConstNotFound } +// Specifies how duplicates should be handled when adding a child item if +// another item exists with the same name in some namespace. +enum DuplicateCheckingMode { + ForbidDuplicateModules, + ForbidDuplicateTypes, + ForbidDuplicateValues, + ForbidDuplicateTypesAndValues, + OverwriteDuplicates +} + +impl DuplicateCheckingMode : cmp::Eq { + pure fn eq(other: &DuplicateCheckingMode) -> bool { + (self as uint) == (*other as uint) + } + pure fn ne(other: &DuplicateCheckingMode) -> bool { !self.eq(other) } +} + +// Returns the namespace associated with the given duplicate checking mode, +// or fails for OverwriteDuplicates. This is used for error messages. +fn namespace_for_duplicate_checking_mode(mode: DuplicateCheckingMode) -> + Namespace { + match mode { + ForbidDuplicateModules | ForbidDuplicateTypes | + ForbidDuplicateTypesAndValues => TypeNS, + ForbidDuplicateValues => ValueNS, + OverwriteDuplicates => fail ~"OverwriteDuplicates has no namespace" + } +} + /// One local scope. struct Rib { bindings: HashMap, @@ -490,9 +518,10 @@ impl Privacy : cmp::Eq { } // Records a possibly-private type definition. -enum TypeNsDef { - ModuleDef(Privacy, @Module), - TypeDef(Privacy, def) +struct TypeNsDef { + mut privacy: Privacy, + mut module_def: Option<@Module>, + mut type_def: Option } // Records a possibly-private value definition. @@ -508,7 +537,7 @@ struct NameBindings { mut value_def: Option, //< Meaning in value namespace. // For error reporting - // XXX: Merge me into TypeDef and ValueDef. + // FIXME (#3783): Merge me into TypeNsDef and ValueNsDef. mut type_span: Option, mut value_span: Option, } @@ -521,16 +550,46 @@ impl NameBindings { def_id: Option, legacy_exports: bool, sp: span) { - if self.type_def.is_none() { - let module_ = @Module(parent_link, def_id, legacy_exports); - self.type_def = Some(ModuleDef(privacy, module_)); - self.type_span = Some(sp); + // Merges the module with the existing type def or creates a new one. + let module_ = @Module(parent_link, def_id, legacy_exports); + match self.type_def { + None => { + self.type_def = Some(TypeNsDef { + privacy: privacy, + module_def: Some(module_), + type_def: None + }); + } + Some(copy type_def) => { + self.type_def = Some(TypeNsDef { + privacy: privacy, + module_def: Some(module_), + .. type_def + }); + } } + self.type_span = Some(sp); } /// Records a type definition. fn define_type(privacy: Privacy, def: def, sp: span) { - self.type_def = Some(TypeDef(privacy, def)); + // Merges the type with the existing type def or creates a new one. + match self.type_def { + None => { + self.type_def = Some(TypeNsDef { + privacy: privacy, + module_def: None, + type_def: Some(def) + }); + } + Some(copy type_def) => { + self.type_def = Some(TypeNsDef { + privacy: privacy, + type_def: Some(def), + .. type_def + }); + } + } self.type_span = Some(sp); } @@ -543,8 +602,8 @@ impl NameBindings { /// Returns the module node if applicable. fn get_module_if_available() -> Option<@Module> { match self.type_def { - Some(ModuleDef(_, module_)) => return Some(module_), - None | Some(TypeDef(_, _)) => return None, + Some(type_def) => type_def.module_def, + None => None } } @@ -553,12 +612,12 @@ impl NameBindings { * definition. */ fn get_module() -> @Module { - match self.type_def { - None | Some(TypeDef(*)) => { + match self.get_module_if_available() { + None => { fail ~"get_module called on a node with no module \ definition!" } - Some(ModuleDef(_, module_)) => module_ + Some(module_def) => module_def } } @@ -574,10 +633,23 @@ impl NameBindings { TypeNS => { match self.type_def { None => None, - Some(ModuleDef(_, module_)) => { - module_.def_id.map(|def_id| def_mod(*def_id)) + Some(type_def) => { + // FIXME (#3784): This is reallllly questionable. + // Perhaps the right thing to do is to merge def_mod + // and def_ty. + match type_def.type_def { + Some(type_def) => Some(type_def), + None => { + match type_def.module_def { + Some(module_def) => { + module_def.def_id.map(|def_id| + def_mod(*def_id)) + } + None => None + } + } + } } - Some(TypeDef(_, def)) => Some(def) } } ValueNS => { @@ -594,8 +666,7 @@ impl NameBindings { TypeNS => { match self.type_def { None => None, - Some(ModuleDef(privacy, _)) | Some(TypeDef(privacy, _)) => - Some(privacy) + Some(type_def) => Some(type_def.privacy) } } ValueNS => { @@ -882,9 +953,7 @@ impl Resolver { */ fn add_child(name: ident, reduced_graph_parent: ReducedGraphParent, - // Pass in the namespaces for the child item so that we can - // check for duplicate items in the same namespace - ns: ~[Namespace], + duplicate_checking_mode: DuplicateCheckingMode, // For printing errors sp: span) -> (@NameBindings, ReducedGraphParent) { @@ -904,29 +973,67 @@ impl Resolver { let new_parent = ModuleReducedGraphParent(module_); match module_.children.find(name) { None => { - let child = @NameBindings(); - module_.children.insert(name, child); - return (child, new_parent); + let child = @NameBindings(); + module_.children.insert(name, child); + return (child, new_parent); } Some(child) => { - // We don't want to complain if the multiple definitions - // are in different namespaces. - match ns.find(|n| child.defined_in_namespace(n)) { - Some(ns) => { - self.session.span_err(sp, - fmt!("Duplicate definition of %s %s", - namespace_to_str(ns), - self.session.str_of(name))); - do child.span_for_namespace(ns).iter() |sp| { - self.session.span_note(*sp, - fmt!("First definition of %s %s here:", - namespace_to_str(ns), - self.session.str_of(name))); - } + // Enforce the duplicate checking mode. If we're requesting + // duplicate module checking, check that there isn't a module + // in the module with the same name. If we're requesting + // duplicate type checking, check that there isn't a type in + // the module with the same name. If we're requesting + // duplicate value checking, check that there isn't a value in + // the module with the same name. If we're requesting + // duplicate type checking and duplicate value checking, check + // that there isn't a duplicate type and a duplicate value + // with the same name. If no duplicate checking was requested + // at all, do nothing. + + let mut is_duplicate = false; + match duplicate_checking_mode { + ForbidDuplicateModules => { + is_duplicate = + child.get_module_if_available().is_some(); + } + ForbidDuplicateTypes => { + match child.def_for_namespace(TypeNS) { + Some(def_mod(_)) | None => {} + Some(_) => is_duplicate = true + } + } + ForbidDuplicateValues => { + is_duplicate = child.defined_in_namespace(ValueNS); + } + ForbidDuplicateTypesAndValues => { + match child.def_for_namespace(TypeNS) { + Some(def_mod(_)) | None => {} + Some(_) => is_duplicate = true + }; + if child.defined_in_namespace(ValueNS) { + is_duplicate = true; + } + } + OverwriteDuplicates => {} } - _ => {} - } - return (child, new_parent); + if duplicate_checking_mode != OverwriteDuplicates && + is_duplicate { + // Return an error here by looking up the namespace that + // had the duplicate. + let ns = namespace_for_duplicate_checking_mode( + duplicate_checking_mode); + self.session.span_err(sp, + fmt!("duplicate definition of %s %s", + namespace_to_str(ns), + self.session.str_of(name))); + do child.span_for_namespace(ns).iter() |sp| { + self.session.span_note(*sp, + fmt!("first definition of %s %s here:", + namespace_to_str(ns), + self.session.str_of(name))); + } + } + return (child, new_parent); } } } @@ -987,7 +1094,7 @@ impl Resolver { item_mod(module_) => { let legacy = has_legacy_export_attr(item.attrs); let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[TypeNS], sp); + self.add_child(ident, parent, ForbidDuplicateModules, sp); let parent_link = self.get_parent_link(new_parent, ident); let def_id = { crate: 0, node: item.id }; @@ -999,12 +1106,14 @@ impl Resolver { visit_mod(module_, sp, item.id, new_parent, visitor); } + item_foreign_mod(fm) => { let legacy = has_legacy_export_attr(item.attrs); let new_parent = match fm.sort { named => { let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[TypeNS], sp); + self.add_child(ident, parent, + ForbidDuplicateModules, sp); let parent_link = self.get_parent_link(new_parent, ident); @@ -1028,15 +1137,15 @@ impl Resolver { // These items live in the value namespace. item_const(*) => { - let (name_bindings, _) = self.add_child(ident, parent, - ~[ValueNS], sp); + let (name_bindings, _) = + self.add_child(ident, parent, ForbidDuplicateValues, sp); (*name_bindings).define_value (privacy, def_const(local_def(item.id)), sp); } item_fn(_, purity, _, _) => { - let (name_bindings, new_parent) = self.add_child(ident, parent, - ~[ValueNS], sp); + let (name_bindings, new_parent) = + self.add_child(ident, parent, ForbidDuplicateValues, sp); let def = def_fn(local_def(item.id), purity); (*name_bindings).define_value(privacy, def, sp); @@ -1045,17 +1154,16 @@ impl Resolver { // These items live in the type namespace. item_ty(*) => { - let (name_bindings, _) = self.add_child(ident, parent, - ~[TypeNS], sp); + let (name_bindings, _) = + self.add_child(ident, parent, ForbidDuplicateTypes, sp); (*name_bindings).define_type (privacy, def_ty(local_def(item.id)), sp); } item_enum(enum_definition, _) => { - - let (name_bindings, new_parent) = self.add_child(ident, parent, - ~[TypeNS], sp); + let (name_bindings, new_parent) = + self.add_child(ident, parent, ForbidDuplicateTypes, sp); (*name_bindings).define_type (privacy, def_ty(local_def(item.id)), sp); @@ -1072,7 +1180,7 @@ impl Resolver { // These items live in both the type and value namespaces. item_class(*) => { let (name_bindings, new_parent) = - self.add_child(ident, parent, ~[TypeNS], sp); + self.add_child(ident, parent, ForbidDuplicateTypes, sp); (*name_bindings).define_type (privacy, def_ty(local_def(item.id)), sp); @@ -1083,13 +1191,75 @@ impl Resolver { visit_item(item, new_parent, visitor); } - item_impl(*) => { + item_impl(_, trait_ref_opt, ty, methods) => { + // If this implements an anonymous trait and it has static + // methods, then add all the static methods within to a new + // module, if the type was defined within this module. + // + // FIXME (#3785): This is quite unsatisfactory. Perhaps we + // should modify anonymous traits to only be implementable in + // the same module that declared the type. + + // Bail out early if there are no static methods. + let mut has_static_methods = false; + for methods.each |method| { + match method.self_ty.node { + sty_static => has_static_methods = true, + _ => {} + } + } + + // If there are static methods, then create the module + // and add them. + match (trait_ref_opt, ty) { + (None, @{ id: _, node: ty_path(path, _), span: _ }) if + has_static_methods && path.idents.len() == 1 => { + // Create the module. + let name = path_to_ident(path); + let (name_bindings, new_parent) = + self.add_child(name, + parent, + ForbidDuplicateModules, + sp); + + let parent_link = self.get_parent_link(new_parent, + ident); + let def_id = local_def(item.id); + name_bindings.define_module(privacy, parent_link, + Some(def_id), false, sp); + + let new_parent = ModuleReducedGraphParent( + name_bindings.get_module()); + + // For each static method... + for methods.each |method| { + match method.self_ty.node { + sty_static => { + // Add the static method to the module. + let ident = method.ident; + let (method_name_bindings, _) = + self.add_child(ident, + new_parent, + ForbidDuplicateValues, + method.span); + let def = def_fn(local_def(method.id), + method.purity); + method_name_bindings.define_value( + Public, def, method.span); + } + _ => {} + } + } + } + _ => {} + } + visit_item(item, parent, visitor); } item_trait(_, _, methods) => { - let (name_bindings, new_parent) = self.add_child(ident, parent, - ~[TypeNS], sp); + let (name_bindings, new_parent) = + self.add_child(ident, parent, ForbidDuplicateTypes, sp); // Add the names of all the methods to the trait info. let method_names = @HashMap(); @@ -1103,8 +1273,8 @@ impl Resolver { sty_static => { // which parent to use?? let (method_name_bindings, _) = - self.add_child(ident, new_parent, ~[ValueNS], - ty_m.span); + self.add_child(ident, new_parent, + ForbidDuplicateValues, ty_m.span); let def = def_static_method(local_def(ty_m.id), local_def(item.id), ty_m.purity); @@ -1142,7 +1312,7 @@ impl Resolver { &&visitor: vt) { let ident = variant.node.name; - let (child, _) = self.add_child(ident, parent, ~[ValueNS], + let (child, _) = self.add_child(ident, parent, ForbidDuplicateValues, variant.span); let privacy; @@ -1324,7 +1494,7 @@ impl Resolver { match find_use_stmt_cnum(self.session.cstore, node_id) { Some(crate_id) => { let (child_name_bindings, new_parent) = - self.add_child(name, parent, ~[TypeNS], + self.add_child(name, parent, ForbidDuplicateTypes, view_item.span); let def_id = { crate: crate_id, node: 0 }; @@ -1355,7 +1525,8 @@ impl Resolver { let name = foreign_item.ident; let (name_bindings, new_parent) = - self.add_child(name, parent, ~[ValueNS], foreign_item.span); + self.add_child(name, parent, ForbidDuplicateValues, + foreign_item.span); match foreign_item.node { foreign_item_fn(_, purity, type_parameters) => { @@ -1408,7 +1579,13 @@ impl Resolver { match def { def_mod(def_id) | def_foreign_mod(def_id) => { match copy child_name_bindings.type_def { - None => { + Some(TypeNsDef { module_def: Some(copy module_def), _ }) => { + debug!("(building reduced graph for external crate) \ + already created module"); + module_def.def_id = Some(def_id); + modules.insert(def_id, module_def); + } + Some(_) | None => { debug!("(building reduced graph for \ external crate) building module \ %s", final_ident); @@ -1451,16 +1628,6 @@ impl Resolver { } } } - Some(ModuleDef(_, module_)) => { - debug!("(building reduced graph for \ - external crate) already created \ - module"); - module_.def_id = Some(def_id); - modules.insert(def_id, module_); - } - Some(TypeDef(*)) => { - self.session.bug(~"external module def overwriting type def"); - } } } def_fn(*) | def_static_method(*) | def_const(*) | @@ -1476,8 +1643,7 @@ impl Resolver { // If this is a trait, add all the method names // to the trait info. - match get_method_names_if_trait(self.session.cstore, - def_id) { + match get_method_names_if_trait(self.session.cstore, def_id) { None => { // Nothing to do. } @@ -1547,8 +1713,8 @@ impl Resolver { let (child_name_bindings, new_parent) = self.add_child(ident, ModuleReducedGraphParent(current_module), - // May want a better span - ~[], dummy_sp()); + OverwriteDuplicates, + dummy_sp()); // Define or reuse the module node. match child_name_bindings.type_def { @@ -1572,7 +1738,8 @@ impl Resolver { let (child_name_bindings, new_parent) = self.add_child(final_ident, ModuleReducedGraphParent(current_module), - ~[], dummy_sp()); + OverwriteDuplicates, + dummy_sp()); match path_entry.def_like { dl_def(def) => { @@ -1582,12 +1749,12 @@ impl Resolver { final_ident, new_parent); } dl_impl(_) => { - // Because of the infelicitous way the metadata is - // written, we can't process this impl now. We'll get it - // later. - + // We only process static methods of impls here. debug!("(building reduced graph for external crate) \ - ignoring impl %s", final_ident_str); + processing impl %s", final_ident_str); + + // FIXME (#3786): Cross-crate static methods in anonymous + // traits. } dl_field => { debug!("(building reduced graph for external crate) \ @@ -2310,18 +2477,34 @@ impl Resolver { return Indeterminate; } Success(target) => { + // Check to see whether there are type bindings, and, if + // so, whether there is a module within. match target.bindings.type_def { - None | Some(TypeDef(*)) => { - // Not a module. + Some(copy type_def) => { + match type_def.module_def { + None => { + // Not a module. + self.session.span_err(span, + fmt!("not a \ + module: %s", + self.session. + str_of( + name))); + return Failed; + } + Some(copy module_def) => { + search_module = module_def; + } + } + } + None => { + // There are no type bindings at all. self.session.span_err(span, fmt!("not a module: %s", - self.session. - str_of(name))); + self.session.str_of( + name))); return Failed; } - Some(ModuleDef(_, copy module_)) => { - search_module = module_; - } } } } @@ -2469,14 +2652,24 @@ impl Resolver { match self.resolve_item_in_lexical_scope(module_, name, TypeNS) { Success(target) => { match target.bindings.type_def { - None | Some(TypeDef(*)) => { + Some(type_def) => { + match type_def.module_def { + None => { + error!("!!! (resolving module in lexical \ + scope) module wasn't actually a \ + module!"); + return Failed; + } + Some(module_def) => { + return Success(module_def); + } + } + } + None => { error!("!!! (resolving module in lexical scope) module wasn't actually a module!"); return Failed; } - Some(ModuleDef(_, module_)) => { - return Success(module_); - } } } Indeterminate => { @@ -3403,7 +3596,6 @@ impl Resolver { self_binding: SelfBinding, capture_clause: CaptureClause, visitor: ResolveVisitor) { - // Check each element of the capture clause. match capture_clause { NoCaptureClause => { @@ -3495,7 +3687,6 @@ impl Resolver { fn resolve_type_parameters(type_parameters: ~[ty_param], visitor: ResolveVisitor) { - for type_parameters.each |type_parameter| { for type_parameter.bounds.each |bound| { match *bound { @@ -3517,7 +3708,6 @@ impl Resolver { methods: ~[@method], optional_destructor: Option, visitor: ResolveVisitor) { - // If applicable, create a rib for the type parameters. let outer_type_parameter_count = (*type_parameters).len(); let borrowed_type_parameters: &~[ty_param] = &*type_parameters; @@ -3619,23 +3809,21 @@ impl Resolver { self_type: @Ty, methods: ~[@method], visitor: ResolveVisitor) { - // If applicable, create a rib for the type parameters. let outer_type_parameter_count = type_parameters.len(); let borrowed_type_parameters: &~[ty_param] = &type_parameters; do self.with_type_parameter_rib(HasTypeParameters (borrowed_type_parameters, id, 0u, NormalRibKind)) { - // Resolve the type parameters. self.resolve_type_parameters(type_parameters, visitor); // Resolve the trait reference, if necessary. let original_trait_refs = self.current_trait_refs; match opt_trait_reference { - Some(trait_reference) => { - let new_trait_refs = @DVec(); - match self.resolve_path( + Some(trait_reference) => { + let new_trait_refs = @DVec(); + match self.resolve_path( trait_reference.path, TypeNS, true, visitor) { None => { self.session.span_err(span, @@ -3649,10 +3837,10 @@ impl Resolver { (*new_trait_refs).push(def_id_of_def(def)); } } - // Record the current set of trait references. - self.current_trait_refs = Some(new_trait_refs); - } - None => () + // Record the current set of trait references. + self.current_trait_refs = Some(new_trait_refs); + } + None => () } // Resolve the self type. diff --git a/src/test/run-pass/anon-trait-static-method.rs b/src/test/run-pass/anon-trait-static-method.rs new file mode 100644 index 000000000000..6c4e9abc5ff7 --- /dev/null +++ b/src/test/run-pass/anon-trait-static-method.rs @@ -0,0 +1,15 @@ +struct Foo { + x: int +} + +impl Foo { + static fn new() -> Foo { + Foo { x: 3 } + } +} + +fn main() { + let x = Foo::new(); + io::println(x.x.to_str()); +} + From a92c3db0b34905e7a828bb72931b791818a02b6b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 16 Oct 2012 20:19:34 -0700 Subject: [PATCH 213/292] add missing pub from multifile example in sec 12.3 --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 8746cf026f9e..645e150b40a7 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -2360,7 +2360,7 @@ these two files: ~~~~ // world.rs #[link(name = "world", vers = "1.0")]; -fn explore() -> ~str { ~"world" } +pub fn explore() -> ~str { ~"world" } ~~~~ ~~~~ {.xfail-test} From 1679960889498d389af1869429b30a7a4360a929 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 16 Oct 2012 22:13:41 -0700 Subject: [PATCH 214/292] Change a use of map::get to map::find --- src/rustc/middle/region.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index 5c70cd3e2795..95280032ae0a 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -640,8 +640,8 @@ fn determine_rp_in_ty(ty: @ast::Ty, // that as a direct dependency. match ty.node { ast::ty_path(path, id) => { - match cx.def_map.get(id) { - ast::def_ty(did) | ast::def_class(did) => { + match cx.def_map.find(id) { + Some(ast::def_ty(did)) | Some(ast::def_class(did)) => { if did.crate == ast::local_crate { if cx.opt_region_is_relevant(path.rp) { cx.add_dep(did.node); From 081a0434fb222b3f182ee6be903b6536c85396d7 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 16 Oct 2012 22:13:55 -0700 Subject: [PATCH 215/292] Remove integer suffixes --- src/rustc/middle/typeck/astconv.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index b8ff637f7dd3..da7a71b3efbf 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -148,8 +148,8 @@ fn ast_path_to_ty( return {substs: substs, ty: ty}; } -const NO_REGIONS: uint = 1u; -const NO_TPS: uint = 2u; +const NO_REGIONS: uint = 1; +const NO_TPS: uint = 2; // Parses the programmer's textual representation of a type into our // internal notion of a type. `getter` is a function that returns the type From 47c83f1844d033a2ee12aa05eed30112804f4585 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Oct 2012 10:39:01 -0700 Subject: [PATCH 216/292] Export std::net_url::encode_component --- src/libstd/net_url.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index 109e71a3eaa7..8ea9513d1551 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -95,7 +95,7 @@ pub fn encode(s: &str) -> ~str { * This function is compliant with RFC 3986. */ -fn encode_component(s: &str) -> ~str { +pub fn encode_component(s: &str) -> ~str { encode_inner(s, false) } From e94e82cb8ef0491667bc8041d370199aed838f2d Mon Sep 17 00:00:00 2001 From: Ben Striegel Date: Fri, 12 Oct 2012 19:41:16 -0400 Subject: [PATCH 217/292] Extraneous sigil patrol: ~"string literals" --- doc/tutorial.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 645e150b40a7..b411e1232b72 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1502,7 +1502,7 @@ and [`core::str`]. Here are some examples. # fn unwrap_crayon(c: Crayon) -> int { 0 } # fn eat_crayon_wax(i: int) { } # fn store_crayon_in_nasal_cavity(i: uint, c: Crayon) { } -# fn crayon_to_str(c: Crayon) -> ~str { ~"" } +# fn crayon_to_str(c: Crayon) -> &str { "" } let crayons = &[Almond, AntiqueBrass, Apricot]; @@ -1649,11 +1649,11 @@ callers may pass any kind of closure. ~~~~ fn call_twice(f: fn()) { f(); f(); } -call_twice(|| { ~"I am an inferred stack closure"; } ); -call_twice(fn&() { ~"I am also a stack closure"; } ); -call_twice(fn@() { ~"I am a managed closure"; }); -call_twice(fn~() { ~"I am an owned closure"; }); -fn bare_function() { ~"I am a plain function"; } +call_twice(|| { "I am an inferred stack closure"; } ); +call_twice(fn&() { "I am also a stack closure"; } ); +call_twice(fn@() { "I am a managed closure"; }); +call_twice(fn~() { "I am an owned closure"; }); +fn bare_function() { "I am a plain function"; } call_twice(bare_function); ~~~~ @@ -1767,7 +1767,7 @@ And using this function to iterate over a vector: # use println = io::println; each(&[2, 4, 8, 5, 16], |n| { if *n % 2 != 0 { - println(~"found odd number!"); + println("found odd number!"); false } else { true } }); @@ -1784,7 +1784,7 @@ to the next iteration, write `loop`. # use println = io::println; for each(&[2, 4, 8, 5, 16]) |n| { if *n % 2 != 0 { - println(~"found odd number!"); + println("found odd number!"); break; } } @@ -1967,12 +1967,12 @@ impl int: Printable { fn print() { io::println(fmt!("%d", self)) } } -impl ~str: Printable { +impl &str: Printable { fn print() { io::println(self) } } # 1.print(); -# (~"foo").print(); +# ("foo").print(); ~~~~ Methods defined in an implementation of a trait may be called just like @@ -2162,8 +2162,8 @@ additional modules. ~~~~ mod farm { - pub fn chicken() -> ~str { ~"cluck cluck" } - pub fn cow() -> ~str { ~"mooo" } + pub fn chicken() -> &str { "cluck cluck" } + pub fn cow() -> &str { "mooo" } } fn main() { @@ -2360,13 +2360,13 @@ these two files: ~~~~ // world.rs #[link(name = "world", vers = "1.0")]; -pub fn explore() -> ~str { ~"world" } +pub fn explore() -> &str { "world" } ~~~~ ~~~~ {.xfail-test} // main.rs extern mod world; -fn main() { io::println(~"hello " + world::explore()); } +fn main() { io::println("hello " + world::explore()); } ~~~~ Now compile and run like this (adjust to your platform if necessary): From 5e1d0bab8075df5ce06543537296d7294440bd45 Mon Sep 17 00:00:00 2001 From: Ben Striegel Date: Fri, 12 Oct 2012 20:48:45 -0400 Subject: [PATCH 218/292] Sigil patrol: change fn@ fn& fn~ to @fn &fn ~fn This also involves removing references to the old long-form closure syntax, which pcwalton alleges is deprecated and which was never updated for the new forms, e.g. `@fn() {}` is illegal. --- doc/tutorial.md | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index b411e1232b72..67c9bcd82811 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1569,7 +1569,7 @@ let bloop = |well, oh: mygoodness| -> what_the { fail oh(well) }; ~~~~ There are several forms of closure, each with its own role. The most -common, called a _stack closure_, has type `fn&` and can directly +common, called a _stack closure_, has type `&fn` and can directly access local variables in the enclosing scope. ~~~~ @@ -1591,7 +1591,7 @@ pervasively in Rust code. When you need to store a closure in a data structure, a stack closure will not do, since the compiler will refuse to let you store it. For this purpose, Rust provides a type of closure that has an arbitrary -lifetime, written `fn@` (boxed closure, analogous to the `@` pointer +lifetime, written `@fn` (boxed closure, analogous to the `@` pointer type described earlier). This type of closure *is* first-class. A managed closure does not directly access its environment, but merely @@ -1604,8 +1604,9 @@ returns it from a function, and then calls it: ~~~~ # extern mod std; -fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str { - return fn@(s: ~str) -> ~str { s + suffix }; +fn mk_appender(suffix: ~str) -> @fn(~str) -> ~str { + // The compiler knows that we intend this closure to be of type @fn + return |s| s + suffix; } fn main() { @@ -1614,22 +1615,9 @@ fn main() { } ~~~~ -This example uses the long closure syntax, `fn@(s: ~str) ...`. Using -this syntax makes it explicit that we are declaring a boxed -closure. In practice, boxed closures are usually defined with the -short closure syntax introduced earlier, in which case the compiler -infers the type of closure. Thus our managed closure example could -also be written: - -~~~~ -fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str { - return |s| s + suffix; -} -~~~~ - ## Owned closures -Owned closures, written `fn~` in analogy to the `~` pointer type, +Owned closures, written `~fn` in analogy to the `~` pointer type, hold on to things that can safely be sent between processes. They copy the values they close over, much like managed closures, but they also own them: that is, no other code can access @@ -1649,12 +1637,10 @@ callers may pass any kind of closure. ~~~~ fn call_twice(f: fn()) { f(); f(); } -call_twice(|| { "I am an inferred stack closure"; } ); -call_twice(fn&() { "I am also a stack closure"; } ); -call_twice(fn@() { "I am a managed closure"; }); -call_twice(fn~() { "I am an owned closure"; }); -fn bare_function() { "I am a plain function"; } -call_twice(bare_function); +let closure = || { "I'm a closure, and it doesn't matter what type I am"; }; +fn function() { "I'm a normal function"; } +call_twice(closure); +call_twice(function); ~~~~ > ***Note:*** Both the syntax and the semantics will be changing @@ -1715,7 +1701,7 @@ parentheses, where it looks more like a typical block of code. `do` is a convenient way to create tasks with the `task::spawn` -function. `spawn` has the signature `spawn(fn: fn~())`. In other +function. `spawn` has the signature `spawn(fn: ~fn())`. In other words, it is a function that takes an owned closure that takes no arguments. From f7ce3dc55f1bcc8a741951a4b9f090bad61769ae Mon Sep 17 00:00:00 2001 From: Ben Striegel Date: Fri, 12 Oct 2012 21:47:46 -0400 Subject: [PATCH 219/292] Extraneous sigil patrol: turn &[] literals into [] --- doc/tutorial.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 67c9bcd82811..02927c4ddd1b 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1504,7 +1504,7 @@ and [`core::str`]. Here are some examples. # fn store_crayon_in_nasal_cavity(i: uint, c: Crayon) { } # fn crayon_to_str(c: Crayon) -> &str { "" } -let crayons = &[Almond, AntiqueBrass, Apricot]; +let crayons = [Almond, AntiqueBrass, Apricot]; // Check the length of the vector assert crayons.len() == 3; @@ -1679,7 +1679,7 @@ structure. ~~~~ # fn each(v: &[int], op: fn(v: &int)) { } # fn do_some_work(i: &int) { } -each(&[1, 2, 3], |n| { +each([1, 2, 3], |n| { do_some_work(n); }); ~~~~ @@ -1690,7 +1690,7 @@ call that can be written more like a built-in control structure: ~~~~ # fn each(v: &[int], op: fn(v: &int)) { } # fn do_some_work(i: &int) { } -do each(&[1, 2, 3]) |n| { +do each([1, 2, 3]) |n| { do_some_work(n); } ~~~~ @@ -1751,7 +1751,7 @@ And using this function to iterate over a vector: ~~~~ # use each = vec::each; # use println = io::println; -each(&[2, 4, 8, 5, 16], |n| { +each([2, 4, 8, 5, 16], |n| { if *n % 2 != 0 { println("found odd number!"); false @@ -1768,7 +1768,7 @@ to the next iteration, write `loop`. ~~~~ # use each = vec::each; # use println = io::println; -for each(&[2, 4, 8, 5, 16]) |n| { +for each([2, 4, 8, 5, 16]) |n| { if *n % 2 != 0 { println("found odd number!"); break; @@ -2106,7 +2106,7 @@ impl @Rectangle: Drawable { fn draw() { ... } } let c: @Circle = @new_circle(); let r: @Rectangle = @new_rectangle(); -draw_all(&[c as @Drawable, r as @Drawable]); +draw_all([c as @Drawable, r as @Drawable]); ~~~~ We omit the code for `new_circle` and `new_rectangle`; imagine that From ca5506a5dee75eb3ee84eff1f0fa5f5e40f54544 Mon Sep 17 00:00:00 2001 From: Jyun-Yan You Date: Mon, 8 Oct 2012 16:36:09 +0800 Subject: [PATCH 220/292] fix the indentation of foreign constant --- src/libsyntax/print/pprust.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5e37f7e18ece..60b3e005f10a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -433,6 +433,7 @@ fn print_foreign_item(s: ps, item: @ast::foreign_item) { print_type(s, t); word(s.s, ~";"); end(s); // end the head-ibox + end(s); // end the outer cbox } } } From 66151d02f54300bb6f4c326728d6a2d875cdc80a Mon Sep 17 00:00:00 2001 From: Jyun-Yan You Date: Mon, 15 Oct 2012 00:19:54 +0800 Subject: [PATCH 221/292] remove duplicate visibility and fix indentation --- src/libsyntax/print/pprust.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 60b3e005f10a..9668c161ce3d 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -444,7 +444,6 @@ fn print_item(s: ps, &&item: @ast::item) { print_outer_attributes(s, item.attrs); let ann_node = node_item(s, item); s.ann.pre(ann_node); - print_visibility(s, item.vis); match item.node { ast::item_const(ty, expr) => { head(s, visibility_qualified(item.vis, ~"const")); @@ -480,10 +479,10 @@ fn print_item(s: ps, &&item: @ast::item) { ast::named => { word_nbsp(s, ~"mod"); print_ident(s, item.ident); + nbsp(s); } ast::anonymous => {} } - nbsp(s); bopen(s); print_foreign_mod(s, nmod, item.attrs); bclose(s, item.span); @@ -491,7 +490,7 @@ fn print_item(s: ps, &&item: @ast::item) { ast::item_ty(ty, params) => { ibox(s, indent_unit); ibox(s, 0u); - word_nbsp(s, ~"type"); + word_nbsp(s, visibility_qualified(item.vis, ~"type")); print_ident(s, item.ident); print_type_params(s, params); end(s); // end the inner ibox @@ -503,15 +502,15 @@ fn print_item(s: ps, &&item: @ast::item) { end(s); // end the outer ibox } ast::item_enum(enum_definition, params) => { - print_enum_def(s, enum_definition, params, item.ident, item.span); + print_enum_def(s, enum_definition, params, item.ident, item.span, item.vis); } ast::item_class(struct_def, tps) => { - head(s, ~"struct"); + head(s, visibility_qualified(item.vis, ~"struct")); print_struct(s, struct_def, tps, item.ident, item.span); } ast::item_impl(tps, opt_trait, ty, methods) => { - head(s, ~"impl"); + head(s, visibility_qualified(item.vis, ~"impl")); if tps.is_not_empty() { print_type_params(s, tps); space(s.s); @@ -534,7 +533,7 @@ fn print_item(s: ps, &&item: @ast::item) { bclose(s, item.span); } ast::item_trait(tps, traits, methods) => { - head(s, ~"trait"); + head(s, visibility_qualified(item.vis, ~"trait")); print_ident(s, item.ident); print_type_params(s, tps); if vec::len(traits) != 0u { @@ -550,6 +549,7 @@ fn print_item(s: ps, &&item: @ast::item) { bclose(s, item.span); } ast::item_mac({node: ast::mac_invoc_tt(pth, tts), _}) => { + print_visibility(s, item.vis); print_path(s, pth, false); word(s.s, ~"! "); print_ident(s, item.ident); @@ -570,7 +570,7 @@ fn print_item(s: ps, &&item: @ast::item) { fn print_enum_def(s: ps, enum_definition: ast::enum_def, params: ~[ast::ty_param], ident: ast::ident, - span: ast::span) { + span: ast::span, visibility: ast::visibility) { let mut newtype = vec::len(enum_definition.variants) == 1u && ident == enum_definition.variants[0].node.name; @@ -582,9 +582,9 @@ fn print_enum_def(s: ps, enum_definition: ast::enum_def, } if newtype { ibox(s, indent_unit); - word_space(s, ~"enum"); + word_space(s, visibility_qualified(visibility, ~"enum")); } else { - head(s, ~"enum"); + head(s, visibility_qualified(visibility, ~"enum")); } print_ident(s, ident); @@ -877,7 +877,7 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type, indented: uint, attrs: ~[ast::attribute], close_box: bool) { match blk.node.rules { - ast::unsafe_blk => word(s.s, ~"unsafe"), + ast::unsafe_blk => word(s.s, ~"unsafe "), ast::default_blk => () } maybe_print_comment(s, blk.span.lo); From 7236472e67a526d996570333669beb9d2dfa2128 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Oct 2012 11:21:45 -0700 Subject: [PATCH 222/292] word => word_space --- src/libsyntax/print/pprust.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9668c161ce3d..a57dd0bc5818 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -877,7 +877,7 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type, indented: uint, attrs: ~[ast::attribute], close_box: bool) { match blk.node.rules { - ast::unsafe_blk => word(s.s, ~"unsafe "), + ast::unsafe_blk => word_space(s, ~"unsafe"), ast::default_blk => () } maybe_print_comment(s, blk.span.lo); From b532a8e5856d525bb7121f4bc00603b91bc2cc5d Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Oct 2012 11:23:02 -0700 Subject: [PATCH 223/292] Line length --- src/libsyntax/print/pprust.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a57dd0bc5818..3fc2bcda9018 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -502,7 +502,8 @@ fn print_item(s: ps, &&item: @ast::item) { end(s); // end the outer ibox } ast::item_enum(enum_definition, params) => { - print_enum_def(s, enum_definition, params, item.ident, item.span, item.vis); + print_enum_def(s, enum_definition, params, item.ident, + item.span, item.vis); } ast::item_class(struct_def, tps) => { head(s, visibility_qualified(item.vis, ~"struct")); From 32baf1c54c4214f5a50da53979008ef9bcdad359 Mon Sep 17 00:00:00 2001 From: Kevin Cantu Date: Thu, 11 Oct 2012 16:54:31 -0700 Subject: [PATCH 224/292] Add a module to getopts to support verbose option definition This is built on top of the existing functionality, but adds a `groups` module which defines functions allowing the user to specify whole short/long/description groups at once and provides a usage message. --- src/libcore/str.rs | 62 ++++++ src/libstd/getopts.rs | 412 ++++++++++++++++++++++++++++++++++++- src/rustc/driver/driver.rs | 92 ++++++--- src/rustc/driver/rustc.rs | 48 +---- 4 files changed, 546 insertions(+), 68 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index aff4c50cfd2d..c32858fc1e32 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -203,6 +203,13 @@ pub pure fn connect(v: &[~str], sep: &str) -> ~str { move s } +/// Given a string, make a new string with repeated copies of it +pub fn repeat(ss: &str, nn: uint) -> ~str { + let mut acc = ~""; + for nn.times { acc += ss; } + return acc; +} + /* Section: Adding to and removing from a string */ @@ -573,6 +580,40 @@ pub pure fn words(s: &str) -> ~[~str] { split_nonempty(s, |c| char::is_whitespace(c)) } +/** Split a string into a vector of substrings, + * each of which is less than a limit + */ +pub fn split_within(ss: &str, lim: uint) -> ~[~str] { + let words = str::words(ss); + + // empty? + if words == ~[] { return ~[]; } + + let mut rows : ~[~str] = ~[]; + let mut row : ~str = ~""; + + for words.each |wptr| { + let word = *wptr; + + // if adding this word to the row would go over the limit, + // then start a new row + if str::len(row) + str::len(word) + 1 > lim { + rows += [row]; // save previous row + row = word; // start a new one + } else { + if str::len(row) > 0 { row += ~" " } // separate words + row += word; // append to this row + } + } + + // save the last row + if row != ~"" { rows += [row]; } + + return rows; +} + + + /// Convert a string to lowercase. ASCII only pub pure fn to_lower(s: &str) -> ~str { map(s, @@ -2465,6 +2506,18 @@ mod tests { assert ~[] == words(~""); } + #[test] + fn test_split_within() { + assert split_within(~"", 0) == ~[]; + assert split_within(~"", 15) == ~[]; + assert split_within(~"hello", 15) == ~[~"hello"]; + + let data = ~"\nMary had a little lamb\nLittle lamb\n"; + assert split_within(data, 15) == ~[~"Mary had a little", + ~"lamb Little", + ~"lamb"]; + } + #[test] fn test_find_str() { // byte positions @@ -2540,6 +2593,15 @@ mod tests { t(~[~"hi"], ~" ", ~"hi"); } + #[test] + fn test_repeat() { + assert repeat(~"x", 4) == ~"xxxx"; + assert repeat(~"hi", 4) == ~"hihihihi"; + assert repeat(~"ไท华", 3) == ~"ไท华ไท华ไท华"; + assert repeat(~"", 4) == ~""; + assert repeat(~"hi", 0) == ~""; + } + #[test] fn test_to_upper() { // libc::toupper, and hence str::to_upper diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs index 6da51571e34a..8d77b88aba23 100644 --- a/src/libstd/getopts.rs +++ b/src/libstd/getopts.rs @@ -82,7 +82,7 @@ pub type Opt = {name: Name, hasarg: HasArg, occur: Occur}; fn mkname(nm: &str) -> Name { let unm = str::from_slice(nm); - return if str::len(nm) == 1u { + return if nm.len() == 1u { Short(str::char_at(unm, 0u)) } else { Long(unm) }; } @@ -114,6 +114,22 @@ impl Occur : Eq { pure fn ne(other: &Occur) -> bool { !self.eq(other) } } +impl HasArg : Eq { + pure fn eq(other: &HasArg) -> bool { + (self as uint) == ((*other) as uint) + } + pure fn ne(other: &HasArg) -> bool { !self.eq(other) } +} + +impl Opt : Eq { + pure fn eq(other: &Opt) -> bool { + self.name == (*other).name && + self.hasarg == (*other).hasarg && + self.occur == (*other).occur + } + pure fn ne(other: &Opt) -> bool { !self.eq(other) } +} + /// Create an option that is required and takes an argument pub fn reqopt(name: &str) -> Opt { return {name: mkname(name), hasarg: Yes, occur: Req}; @@ -150,8 +166,29 @@ enum Optval { Val(~str), Given, } */ pub type Matches = {opts: ~[Opt], vals: ~[~[Optval]], free: ~[~str]}; +impl Optval : Eq { + pure fn eq(other: &Optval) -> bool { + match self { + Val(ref s) => match *other { Val (ref os) => s == os, + Given => false }, + Given => match *other { Val(_) => false, + Given => true } + } + } + pure fn ne(other: &Optval) -> bool { !self.eq(other) } +} + +impl Matches : Eq { + pure fn eq(other: &Matches) -> bool { + self.opts == (*other).opts && + self.vals == (*other).vals && + self.free == (*other).free + } + pure fn ne(other: &Matches) -> bool { !self.eq(other) } +} + fn is_arg(arg: &str) -> bool { - return str::len(arg) > 1u && arg[0] == '-' as u8; + return arg.len() > 1u && arg[0] == '-' as u8; } fn name_str(nm: &Name) -> ~str { @@ -177,6 +214,35 @@ pub enum Fail_ { UnexpectedArgument(~str), } +impl Fail_ : Eq { + // this whole thing should be easy to infer... + pure fn eq(other: &Fail_) -> bool { + match self { + ArgumentMissing(ref s) => { + match *other { ArgumentMissing(ref so) => s == so, + _ => false } + } + UnrecognizedOption(ref s) => { + match *other { UnrecognizedOption(ref so) => s == so, + _ => false } + } + OptionMissing(ref s) => { + match *other { OptionMissing(ref so) => s == so, + _ => false } + } + OptionDuplicated(ref s) => { + match *other { OptionDuplicated(ref so) => s == so, + _ => false } + } + UnexpectedArgument(ref s) => { + match *other { UnexpectedArgument(ref so) => s == so, + _ => false } + } + } + } + pure fn ne(other: &Fail_) -> bool { !self.eq(other) } +} + /// Convert a `fail_` enum into an error string pub fn fail_str(f: Fail_) -> ~str { return match f { @@ -220,7 +286,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe { let mut i = 0u; while i < l { let cur = args[i]; - let curlen = str::len(cur); + let curlen = cur.len(); if !is_arg(cur) { free.push(cur); } else if cur == ~"--" { @@ -444,6 +510,194 @@ impl FailType : Eq { pure fn ne(other: &FailType) -> bool { !self.eq(other) } } +/** A module which provides a way to specify descriptions and + * groups of short and long option names, together. + */ +pub mod groups { + + /** one group of options, e.g., both -h and --help, along with + * their shared description and properties + */ + pub type OptGroup = { + short_name: ~str, + long_name: ~str, + hint: ~str, + desc: ~str, + hasarg: HasArg, + occur: Occur + }; + + impl OptGroup : Eq { + pure fn eq(other: &OptGroup) -> bool { + self.short_name == (*other).short_name && + self.long_name == (*other).long_name && + self.hint == (*other).hint && + self.desc == (*other).desc && + self.hasarg == (*other).hasarg && + self.occur == (*other).occur + } + pure fn ne(other: &OptGroup) -> bool { !self.eq(other) } + } + + /// Create a long option that is required and takes an argument + pub fn reqopt(short_name: &str, long_name: &str, + desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: str::from_slice(hint), + desc: str::from_slice(desc), + hasarg: Yes, + occur: Req}; + } + + /// Create a long option that is optional and takes an argument + pub fn optopt(short_name: &str, long_name: &str, + desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: str::from_slice(hint), + desc: str::from_slice(desc), + hasarg: Yes, + occur: Optional}; + } + + /// Create a long option that is optional and does not take an argument + pub fn optflag(short_name: &str, long_name: &str, + desc: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: ~"", + desc: str::from_slice(desc), + hasarg: No, + occur: Optional}; + } + + /// Create a long option that is optional and takes an optional argument + pub fn optflagopt(short_name: &str, long_name: &str, + desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: str::from_slice(hint), + desc: str::from_slice(desc), + hasarg: Maybe, + occur: Optional}; + } + + /** + * Create a long option that is optional, takes an argument, and may occur + * multiple times + */ + pub fn optmulti(short_name: &str, long_name: &str, + desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert len == 1 || len == 0; + return {short_name: str::from_slice(short_name), + long_name: str::from_slice(long_name), + hint: str::from_slice(hint), + desc: str::from_slice(desc), + hasarg: Yes, + occur: Multi}; + } + + // translate OptGroup into Opt + // (both short and long names correspond to different Opts) + pub fn long_to_short(lopt: &OptGroup) -> ~[Opt] { + match ((*lopt).short_name.len(), + (*lopt).long_name.len()) { + + (0,0) => fail ~"this long-format option was given no name", + + (0,_) => ~[{name: Long(((*lopt).long_name)), + hasarg: (*lopt).hasarg, + occur: (*lopt).occur}], + + (1,0) => ~[{name: Short(str::char_at((*lopt).short_name, 0)), + hasarg: (*lopt).hasarg, + occur: (*lopt).occur}], + + (1,_) => ~[{name: Short(str::char_at((*lopt).short_name, 0)), + hasarg: (*lopt).hasarg, + occur: (*lopt).occur}, + {name: Long(((*lopt).long_name)), + hasarg: (*lopt).hasarg, + occur: (*lopt).occur}], + + (_,_) => fail ~"something is wrong with the long-form opt" + } + } + + /* + * Parse command line args with the provided long format options + */ + pub fn getopts(args: &[~str], opts: &[OptGroup]) -> Result { + ::getopts::getopts(args, vec::flat_map(opts, long_to_short)) + } + + /** + * Derive a usage message from a set of long options + */ + pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { + + let desc_sep = ~"\n" + str::repeat(~" ", 24); + + let rows = vec::map(opts, |optref| { + let short_name = (*optref).short_name; + let long_name = (*optref).long_name; + let hint = (*optref).hint; + let desc = (*optref).desc; + let hasarg = (*optref).hasarg; + + let mut row = str::repeat(~" ", 4); + + // short option + row += match short_name.len() { + 0 => ~"", + 1 => ~"-" + short_name + " ", + _ => fail ~"the short name should only be 1 char long", + }; + + // long option + row += match long_name.len() { + 0 => ~"", + _ => ~"--" + long_name + " ", + }; + + // arg + row += match hasarg { + No => ~"", + Yes => hint, + Maybe => ~"[" + hint + ~"]", + }; + + // here we just need to indent the start of the description + let rowlen = row.len(); + row += if rowlen < 24 { + str::repeat(~" ", 24 - rowlen) + } else { + desc_sep + }; + + // wrapped description + row += str::connect(str::split_within(desc, 54), desc_sep); + + row + }); + + return str::from_slice(brief) + + ~"\n\nOptions:\n" + + str::connect(rows, ~"\n") + + ~"\n\n"; + } +} // end groups module + #[cfg(test)] mod tests { #[legacy_exports]; @@ -943,6 +1197,158 @@ mod tests { assert opts_present(matches, ~[~"L"]); assert opts_str(matches, ~[~"L"]) == ~"foo"; } + + #[test] + fn test_groups_reqopt() { + let opt = groups::reqopt(~"b", ~"banana", ~"some bananas", ~"VAL"); + assert opt == { short_name: ~"b", + long_name: ~"banana", + hint: ~"VAL", + desc: ~"some bananas", + hasarg: Yes, + occur: Req } + } + + #[test] + fn test_groups_optopt() { + let opt = groups::optopt(~"a", ~"apple", ~"some apples", ~"VAL"); + assert opt == { short_name: ~"a", + long_name: ~"apple", + hint: ~"VAL", + desc: ~"some apples", + hasarg: Yes, + occur: Optional } + } + + #[test] + fn test_groups_optflag() { + let opt = groups::optflag(~"k", ~"kiwi", ~"some kiwis"); + assert opt == { short_name: ~"k", + long_name: ~"kiwi", + hint: ~"", + desc: ~"some kiwis", + hasarg: No, + occur: Optional } + } + + #[test] + fn test_groups_optflagopt() { + let opt = groups::optflagopt(~"p", ~"pineapple", + ~"some pineapples", ~"VAL"); + assert opt == { short_name: ~"p", + long_name: ~"pineapple", + hint: ~"VAL", + desc: ~"some pineapples", + hasarg: Maybe, + occur: Optional } + } + + #[test] + fn test_groups_optmulti() { + let opt = groups::optmulti(~"l", ~"lime", + ~"some limes", ~"VAL"); + assert opt == { short_name: ~"l", + long_name: ~"lime", + hint: ~"VAL", + desc: ~"some limes", + hasarg: Yes, + occur: Multi } + } + + #[test] + fn test_groups_long_to_short() { + let short = ~[reqopt(~"b"), reqopt(~"banana")]; + let verbose = groups::reqopt(~"b", ~"banana", + ~"some bananas", ~"VAL"); + + assert groups::long_to_short(&verbose) == short; + } + + #[test] + fn test_groups_getopts() { + let short = ~[ + reqopt(~"b"), reqopt(~"banana"), + optopt(~"a"), optopt(~"apple"), + optflag(~"k"), optflagopt(~"kiwi"), + optflagopt(~"p"), + optmulti(~"l") + ]; + + let verbose = ~[ + groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"), + groups::optopt(~"a", ~"apple", ~"Desc", ~"VAL"), + groups::optflag(~"k", ~"kiwi", ~"Desc"), + groups::optflagopt(~"p", ~"", ~"Desc", ~"VAL"), + groups::optmulti(~"l", ~"", ~"Desc", ~"VAL"), + ]; + + let sample_args = ~[~"-k", ~"15", ~"--apple", ~"1", ~"k", + ~"-p", ~"16", ~"l", ~"35"]; + + // NOTE: we should sort before comparing + assert getopts(sample_args, short) + == groups::getopts(sample_args, verbose); + } + + #[test] + fn test_groups_usage() { + let optgroups = ~[ + groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"), + groups::optopt(~"a", ~"012345678901234567890123456789", + ~"Desc", ~"VAL"), + groups::optflag(~"k", ~"kiwi", ~"Desc"), + groups::optflagopt(~"p", ~"", ~"Desc", ~"VAL"), + groups::optmulti(~"l", ~"", ~"Desc", ~"VAL"), + ]; + + let expected = +~"Usage: fruits + +Options: + -b --banana VAL Desc + -a --012345678901234567890123456789 VAL + Desc + -k --kiwi Desc + -p [VAL] Desc + -l VAL Desc + +"; + + let generated_usage = groups::usage(~"Usage: fruits", optgroups); + + debug!("expected: <<%s>>", expected); + debug!("generated: <<%s>>", generated_usage); + assert generated_usage == expected; + } + + #[test] + fn test_groups_usage_description_wrapping() { + // indentation should be 24 spaces + // lines wrap after 78: or rather descriptions wrap after 54 + + let optgroups = ~[ + groups::optflag(~"k", ~"kiwi", + ~"This is a long description which won't be wrapped..+.."), // 54 + groups::optflag(~"a", ~"apple", + ~"This is a long description which _will_ be wrapped..+.."), // 55 + ]; + + let expected = +~"Usage: fruits + +Options: + -k --kiwi This is a long description which won't be wrapped..+.. + -a --apple This is a long description which _will_ be + wrapped..+.. + +"; + + let usage = groups::usage(~"Usage: fruits", optgroups); + + debug!("expected: <<%s>>", expected); + debug!("generated: <<%s>>", usage); + assert usage == expected + } } // Local Variables: diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index e389f3a4bdf7..1c79f91cf24a 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -10,8 +10,10 @@ use util::ppaux; use back::link; use result::{Ok, Err}; use std::getopts; +use std::getopts::{opt_present}; +use std::getopts::groups; +use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts}; use io::WriterUtil; -use getopts::{optopt, optmulti, optflag, optflagopt, opt_present}; use back::{x86, x86_64}; use std::map::HashMap; use lib::llvm::llvm; @@ -624,27 +626,69 @@ fn parse_pretty(sess: session, &&name: ~str) -> pp_mode { } } -fn opts() -> ~[getopts::Opt] { - return ~[optflag(~"h"), optflag(~"help"), - optflag(~"v"), optflag(~"version"), - optflag(~"emit-llvm"), optflagopt(~"pretty"), - optflag(~"ls"), optflag(~"parse-only"), optflag(~"no-trans"), - optflag(~"O"), optopt(~"opt-level"), optmulti(~"L"), optflag(~"S"), - optopt(~"o"), optopt(~"out-dir"), optflag(~"xg"), - optflag(~"c"), optflag(~"g"), optflag(~"save-temps"), - optopt(~"sysroot"), optopt(~"target"), - optflag(~"jit"), - - optmulti(~"W"), optmulti(~"warn"), - optmulti(~"A"), optmulti(~"allow"), - optmulti(~"D"), optmulti(~"deny"), - optmulti(~"F"), optmulti(~"forbid"), - - optmulti(~"Z"), - - optmulti(~"cfg"), optflag(~"test"), - optflag(~"lib"), optflag(~"bin"), - optflag(~"static"), optflag(~"gc")]; +// rustc command line options +fn optgroups() -> ~[getopts::groups::OptGroup] { + ~[ + optflag(~"", ~"bin", ~"Compile an executable crate (default)"), + optflag(~"c", ~"", ~"Compile and assemble, but do not link"), + optmulti(~"", ~"cfg", ~"Configure the compilation + environment", ~"SPEC"), + optflag(~"", ~"emit-llvm", + ~"Produce an LLVM bitcode file"), + optflag(~"g", ~"", ~"Produce debug info (experimental)"), + optflag(~"", ~"gc", ~"Garbage collect shared data (experimental)"), + optflag(~"h", ~"help",~"Display this message"), + optmulti(~"L", ~"", ~"Add a directory to the library search path", + ~"PATH"), + optflag(~"", ~"lib", ~"Compile a library crate"), + optflag(~"", ~"ls", ~"List the symbols defined by a library crate"), + optflag(~"", ~"jit", ~"Execute using JIT (experimental)"), + optflag(~"", ~"no-trans", + ~"Run all passes except translation; no output"), + optflag(~"O", ~"", ~"Equivalent to --opt-level=2"), + optopt(~"o", ~"", ~"Write output to ", ~"FILENAME"), + optopt(~"", ~"opt-level", + ~"Optimize with possible levels 0-3", ~"LEVEL"), + optopt( ~"", ~"out-dir", + ~"Write output to compiler-chosen filename + in ", ~"DIR"), + optflag(~"", ~"parse-only", + ~"Parse only; do not compile, assemble, or link"), + optflagopt(~"", ~"pretty", + ~"Pretty-print the input instead of compiling; + valid types are: normal (un-annotated source), + expanded (crates expanded), + typed (crates expanded, with type annotations), + or identified (fully parenthesized, + AST nodes and blocks with IDs)", ~"TYPE"), + optflag(~"S", ~"", ~"Compile only; do not assemble or link"), + optflag(~"", ~"xg", ~"Extra debugging info (experimental)"), + optflag(~"", ~"save-temps", + ~"Write intermediate files (.bc, .opt.bc, .o) + in addition to normal output"), + optflag(~"", ~"static", + ~"Use or produce static libraries or binaries + (experimental)"), + optopt(~"", ~"sysroot", + ~"Override the system root", ~"PATH"), + optflag(~"", ~"test", ~"Build a test harness"), + optopt(~"", ~"target", + ~"Target triple cpu-manufacturer-kernel[-os] + to compile for (see + http://sources.redhat.com/autobook/autobook/autobook_17.html + for detail)", ~"TRIPLE"), + optmulti(~"W", ~"warn", + ~"Set lint warnings", ~"OPT"), + optmulti(~"A", ~"allow", + ~"Set lint allowed", ~"OPT"), + optmulti(~"D", ~"deny", + ~"Set lint denied", ~"OPT"), + optmulti(~"F", ~"forbid", + ~"Set lint forbidden", ~"OPT"), + optmulti(~"Z", ~"", ~"Set internal debugging options", "FLAG"), + optflag( ~"v", ~"version", + ~"Print version info and exit"), + ] } type output_filenames = @{out_filename:Path, obj_filename:Path}; @@ -742,7 +786,7 @@ mod test { #[test] fn test_switch_implies_cfg_test() { let matches = - match getopts::getopts(~[~"--test"], opts()) { + match getopts(~[~"--test"], optgroups()) { Ok(m) => m, Err(f) => fail ~"test_switch_implies_cfg_test: " + getopts::fail_str(f) @@ -759,7 +803,7 @@ mod test { #[test] fn test_switch_implies_cfg_test_unless_cfg_test() { let matches = - match getopts::getopts(~[~"--test", ~"--cfg=test"], opts()) { + match getopts(~[~"--test", ~"--cfg=test"], optgroups()) { Ok(m) => m, Err(f) => { fail ~"test_switch_implies_cfg_test_unless_cfg_test: " + diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index 5833723ec101..b7783307cc31 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -16,6 +16,7 @@ use io::ReaderUtil; use std::getopts; use std::map::HashMap; use getopts::{opt_present}; +use getopts::groups; use rustc::driver::driver::*; use syntax::codemap; use syntax::diagnostic; @@ -31,46 +32,11 @@ fn version(argv0: &str) { } fn usage(argv0: &str) { - io::println(fmt!("Usage: %s [options] \n", argv0) + - ~" -Options: - - --bin Compile an executable crate (default) - -c Compile and assemble, but do not link - --cfg Configure the compilation environment - --emit-llvm Produce an LLVM bitcode file - -g Produce debug info (experimental) - --gc Garbage collect shared data (experimental/temporary) - -h --help Display this message - -L Add a directory to the library search path - --lib Compile a library crate - --ls List the symbols defined by a compiled library crate - --jit Execute using JIT (experimental) - --no-trans Run all passes except translation; no output - -O Equivalent to --opt-level=2 - -o Write output to - --opt-level Optimize with possible levels 0-3 - --out-dir Write output to compiler-chosen filename in - --parse-only Parse only; do not compile, assemble, or link - --pretty [type] Pretty-print the input instead of compiling; - valid types are: normal (un-annotated source), - expanded (crates expanded), typed (crates expanded, - with type annotations), or identified (fully - parenthesized, AST nodes and blocks with IDs) - -S Compile only; do not assemble or link - --save-temps Write intermediate files (.bc, .opt.bc, .o) - in addition to normal output - --static Use or produce static libraries or binaries - (experimental) - --sysroot Override the system root - --test Build a test harness - --target Target cpu-manufacturer-kernel[-os] to compile for - (default: host triple) - (see http://sources.redhat.com/autobook/autobook/ - autobook_17.html for detail) - -W help Print 'lint' options and default settings - -Z help Print internal options for debugging rustc - -v --version Print version info and exit + let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0); + io::println(groups::usage(message, optgroups()) + + ~"Additional help: + -W help Print 'lint' options and default settings + -Z help Print internal options for debugging rustc "); } @@ -127,7 +93,7 @@ fn run_compiler(args: &~[~str], demitter: diagnostic::emitter) { if args.is_empty() { usage(binary); return; } let matches = - match getopts::getopts(args, opts()) { + match getopts::groups::getopts(args, optgroups()) { Ok(m) => m, Err(f) => { early_error(demitter, getopts::fail_str(f)) From f2544d8d80f20e9c1e39c3c455b18ebe1922d1d5 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Oct 2012 12:16:57 -0700 Subject: [PATCH 225/292] Fix long lines --- src/cargo/cargo.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index 322d78004208..a06eb19910be 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -1165,8 +1165,8 @@ fn sync_one_file(c: &Cargo, dir: &Path, src: @Source) -> bool { let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s with key %s", - name, f)); + error(fmt!("signature verification failed for source %s with \ + key %s", name, f)); return false; } @@ -1174,8 +1174,8 @@ fn sync_one_file(c: &Cargo, dir: &Path, src: @Source) -> bool { let e = pgp::verify(&c.root, &srcfile, &srcsigfile); if !e { - error(fmt!("signature verification failed for source %s with key %s", - name, f)); + error(fmt!("signature verification failed for source %s \ + with key %s", name, f)); return false; } } @@ -1276,8 +1276,8 @@ fn sync_one_git(c: &Cargo, dir: &Path, src: @Source) -> bool { let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s with key %s", - name, f)); + error(fmt!("signature verification failed for source %s with \ + key %s", name, f)); rollback(name, dir, false); return false; } @@ -1286,8 +1286,8 @@ fn sync_one_git(c: &Cargo, dir: &Path, src: @Source) -> bool { let e = pgp::verify(&c.root, &srcfile, &srcsigfile); if !e { - error(fmt!("signature verification failed for source %s with key %s", - name, f)); + error(fmt!("signature verification failed for source %s \ + with key %s", name, f)); rollback(name, dir, false); return false; } @@ -1373,8 +1373,8 @@ fn sync_one_curl(c: &Cargo, dir: &Path, src: @Source) -> bool { let r = pgp::verify(&c.root, &pkgfile, &sigfile); if !r { - error(fmt!("signature verification failed for source %s with key %s", - name, f)); + error(fmt!("signature verification failed for source %s with \ + key %s", name, f)); return false; } From fd6be2fa4eac4638174a484529ef782007d0fec1 Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Thu, 4 Oct 2012 18:18:02 -0400 Subject: [PATCH 226/292] std::treemap - changing types to reflect constraints, adding equality check (space expensive) --- src/libstd/treemap.rs | 56 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 8ab0dc7f2e7d..f332c06d0bc3 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -11,28 +11,28 @@ use core::cmp::{Eq, Ord}; use core::option::{Some, None}; use Option = core::Option; -pub type TreeMap = @mut TreeEdge; +pub type TreeMap = @mut TreeEdge; -type TreeEdge = Option<@TreeNode>; +type TreeEdge = Option<@TreeNode>; -enum TreeNode = { +struct TreeNode { key: K, mut value: V, mut left: TreeEdge, mut right: TreeEdge -}; +} /// Create a treemap -pub fn TreeMap() -> TreeMap { @mut None } +pub fn TreeMap() -> TreeMap { @mut None } /// Insert a value into the map pub fn insert(m: &mut TreeEdge, k: K, v: V) { match copy *m { None => { - *m = Some(@TreeNode({key: k, - mut value: v, - mut left: None, - mut right: None})); + *m = Some(@TreeNode {key: k, + mut value: v, + mut left: None, + mut right: None}); return; } Some(node) => { @@ -67,7 +67,8 @@ pub fn find(m: &const TreeEdge, k: K) } /// Visit all pairs in the map in order. -pub fn traverse(m: &const TreeEdge, f: fn((&K), (&V))) { +pub fn traverse(m: &const TreeEdge, + f: fn((&K), (&V))) { match copy *m { None => (), Some(node) => { @@ -79,6 +80,19 @@ pub fn traverse(m: &const TreeEdge, f: fn((&K), (&V))) { } } +/// Compare two treemaps and return true iff +/// they contain same keys and values +pub fn equals(t1: &const TreeEdge, + t2: &const TreeEdge) + -> bool { + let mut v1 = ~[]; + let mut v2 = ~[]; + traverse(t1, |k,v| { v1.push((copy *k, copy *v)) }); + traverse(t2, |k,v| { v2.push((copy *k, copy *v)) }); + return v1 == v2; +} + + #[cfg(test)] mod tests { #[legacy_exports]; @@ -127,6 +141,28 @@ mod tests { traverse(m, |x,y| t(n, *x, *y)); } + #[test] + fn equality() { + let m1 = TreeMap(); + insert(m1, 3, ()); + insert(m1, 0, ()); + insert(m1, 4, ()); + insert(m1, 2, ()); + insert(m1, 1, ()); + let m2 = TreeMap(); + insert(m2, 2, ()); + insert(m2, 1, ()); + insert(m2, 3, ()); + insert(m2, 0, ()); + insert(m2, 4, ()); + + assert equals(m1, m2); + + let m3 = TreeMap(); + assert !equals(m1,m3); + + } + #[test] fn u8_map() { let m = TreeMap(); From bbc90b6bf6082f32cccef1011ac6b862a02957c4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Oct 2012 12:59:10 -0700 Subject: [PATCH 227/292] Fix whitespace --- src/libstd/treemap.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index f332c06d0bc3..e4b6c9b5b9a9 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -67,7 +67,7 @@ pub fn find(m: &const TreeEdge, k: K) } /// Visit all pairs in the map in order. -pub fn traverse(m: &const TreeEdge, +pub fn traverse(m: &const TreeEdge, f: fn((&K), (&V))) { match copy *m { None => (), @@ -80,10 +80,10 @@ pub fn traverse(m: &const TreeEdge, } } -/// Compare two treemaps and return true iff +/// Compare two treemaps and return true iff /// they contain same keys and values pub fn equals(t1: &const TreeEdge, - t2: &const TreeEdge) + t2: &const TreeEdge) -> bool { let mut v1 = ~[]; let mut v2 = ~[]; From cf8bded7aae0673f9275de7948508da3c2b58650 Mon Sep 17 00:00:00 2001 From: Arkaitz Jimenez Date: Wed, 17 Oct 2012 00:12:07 +0200 Subject: [PATCH 228/292] Enable configure to detect 32 bit systems on 64 bit kernels These systems run 32 bit binaries so arch needs to be forced to 32 bits. --- configure | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/configure b/configure index e67ea3af5f38..40c6acead0ef 100755 --- a/configure +++ b/configure @@ -257,6 +257,16 @@ case $CFG_CPUTYPE in err "unknown CPU type: $CFG_CPUTYPE" esac +# Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation +if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ] +then + file -L "$SHELL" | grep -q "x86[_-]64" + if [ $? != 0 ]; then + CFG_CPUTYPE=i686 + fi +fi + + DEFAULT_HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}" CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/" From d9f1426e69410f0eda9b4c1b2e87042a8bbda41d Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Oct 2012 13:47:24 -0700 Subject: [PATCH 229/292] Fix copy warnings in str --- src/libcore/str.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index da1defc38b18..abd9621cf0f4 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -207,7 +207,7 @@ pub pure fn connect(v: &[~str], sep: &str) -> ~str { pub fn repeat(ss: &str, nn: uint) -> ~str { let mut acc = ~""; for nn.times { acc += ss; } - return acc; + move acc } /* @@ -593,23 +593,23 @@ pub fn split_within(ss: &str, lim: uint) -> ~[~str] { let mut row : ~str = ~""; for words.each |wptr| { - let word = *wptr; + let word = copy *wptr; // if adding this word to the row would go over the limit, // then start a new row - if str::len(row) + str::len(word) + 1 > lim { - rows += [row]; // save previous row - row = word; // start a new one + if row.len() + word.len() + 1 > lim { + rows.push(copy row); // save previous row + row = move word; // start a new one } else { - if str::len(row) > 0 { row += ~" " } // separate words + if row.len() > 0 { row += ~" " } // separate words row += word; // append to this row } } // save the last row - if row != ~"" { rows += [row]; } + if row != ~"" { rows.push(move row); } - return rows; + move rows } From 7dde840dc6b077974d48ae7c966ea16a0e36f3f6 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Oct 2012 13:47:24 -0700 Subject: [PATCH 230/292] Fix copy warnings in str --- src/libcore/str.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index abd9621cf0f4..26f29e388cb0 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2527,9 +2527,10 @@ mod tests { assert split_within(~"hello", 15) == ~[~"hello"]; let data = ~"\nMary had a little lamb\nLittle lamb\n"; - assert split_within(data, 15) == ~[~"Mary had a little", - ~"lamb Little", - ~"lamb"]; + error!("~~~~ %?", split_within(data, 15)); + assert split_within(data, 15) == ~[~"Mary had a", + ~"little lamb", + ~"Little lamb"]; } #[test] From e7e1bab27fa8341467b5160506bbd580b5f6bbb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Br=C3=BCschweiler?= Date: Tue, 9 Oct 2012 11:59:03 +0200 Subject: [PATCH 231/292] libsyntax: refactor the parser to consider foreign items as items parse_item_or_view_item() would drop visibility if none of the conditions following it would hold. This was the case when parsing extern {} blocks, where the function was only used to parse view items, but discarded the visibility of the first not-view item. --- src/libcore/str.rs | 2 +- src/libsyntax/parse/parser.rs | 86 +++++++++++++------ src/test/compile-fail/duplicate-visibility.rs | 4 + 3 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 src/test/compile-fail/duplicate-visibility.rs diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 26f29e388cb0..d59f36e06813 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1952,7 +1952,7 @@ pub mod raw { } /// Converts a vector of bytes to a string. - pub pub unsafe fn from_bytes(v: &[const u8]) -> ~str { + pub unsafe fn from_bytes(v: &[const u8]) -> ~str { do vec::as_const_buf(v) |buf, len| { from_buf_len(buf, len) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e29620a7e79d..cbad662800b5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -124,12 +124,13 @@ type item_info = (ident, item_, Option<~[attribute]>); enum item_or_view_item { iovi_none, iovi_item(@item), + iovi_foreign_item(@foreign_item), iovi_view_item(@view_item) } enum view_item_parse_mode { VIEW_ITEMS_AND_ITEMS_ALLOWED, - VIEW_ITEMS_ALLOWED, + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED, IMPORTS_AND_ITEMS_ALLOWED } @@ -2184,7 +2185,7 @@ impl Parser { let item_attrs = vec::append(first_item_attrs, item_attrs); - match self.parse_item_or_view_item(item_attrs, true) { + match self.parse_item_or_view_item(item_attrs, true, false) { iovi_item(i) => { let mut hi = i.span.hi; let decl = @spanned(lo, hi, decl_item(i)); @@ -2194,6 +2195,9 @@ impl Parser { self.span_fatal(vi.span, ~"view items must be declared at \ the top of the block"); } + iovi_foreign_item(_) => { + self.fatal(~"foreign items are not allowed here"); + } iovi_none() => { /* fallthrough */ } } @@ -2259,7 +2263,7 @@ impl Parser { let mut stmts = ~[]; let mut expr = None; - let {attrs_remaining, view_items, items: items} = + let {attrs_remaining, view_items, items: items, _} = self.parse_items_and_view_items(first_item_attrs, IMPORTS_AND_ITEMS_ALLOWED); @@ -2844,7 +2848,7 @@ impl Parser { fn parse_mod_items(term: token::Token, +first_item_attrs: ~[attribute]) -> _mod { // Shouldn't be any view items since we've already parsed an item attr - let {attrs_remaining, view_items, items: starting_items} = + let {attrs_remaining, view_items, items: starting_items, _} = self.parse_items_and_view_items(first_item_attrs, VIEW_ITEMS_AND_ITEMS_ALLOWED); let mut items: ~[@item] = move starting_items; @@ -2858,7 +2862,7 @@ impl Parser { } debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)", attrs); - match self.parse_item_or_view_item(attrs, true) { + match self.parse_item_or_view_item(attrs, true, false) { iovi_item(item) => items.push(item), iovi_view_item(view_item) => { self.span_fatal(view_item.span, ~"view items must be \ @@ -2958,11 +2962,11 @@ impl Parser { +first_item_attrs: ~[attribute]) -> foreign_mod { // Shouldn't be any view items since we've already parsed an item attr - let {attrs_remaining, view_items, items: _} = + let {attrs_remaining, view_items, items: _, foreign_items} = self.parse_items_and_view_items(first_item_attrs, - VIEW_ITEMS_ALLOWED); + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED); - let mut items: ~[@foreign_item] = ~[]; + let mut items: ~[@foreign_item] = move foreign_items; let mut initial_attrs = attrs_remaining; while self.token != token::RBRACE { let attrs = vec::append(initial_attrs, @@ -2971,7 +2975,7 @@ impl Parser { items.push(self.parse_foreign_item(attrs)); } return {sort: sort, view_items: view_items, - items: items}; + items: items}; } fn parse_item_foreign_mod(lo: uint, @@ -3229,8 +3233,11 @@ impl Parser { } } - fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool) + fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool, + foreign_items_allowed: bool) -> item_or_view_item { + assert items_allowed != foreign_items_allowed; + maybe_whole!(iovi self,nt_item); let lo = self.span.lo; @@ -3248,6 +3255,9 @@ impl Parser { return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); + } else if foreign_items_allowed && self.is_keyword(~"const") { + let item = self.parse_item_foreign_const(visibility, attrs); + return iovi_foreign_item(item); } else if items_allowed && self.is_keyword(~"fn") && !self.fn_expr_lookahead(self.look_ahead(1u)) { @@ -3262,6 +3272,10 @@ impl Parser { return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); + } else if foreign_items_allowed && + (self.is_keyword(~"fn") || self.is_keyword(~"pure")) { + let item = self.parse_item_foreign_fn(visibility, attrs); + return iovi_foreign_item(item); } else if items_allowed && self.is_keyword(~"unsafe") && self.look_ahead(1u) != token::LBRACE { self.bump(); @@ -3348,16 +3362,24 @@ impl Parser { return iovi_item(self.mk_item(lo, self.last_span.hi, id, item_, visibility, attrs)); } else { + if visibility != inherited { + let mut s = ~"unmatched visibility `"; + s += if visibility == public { ~"pub" } else { ~"priv" }; + s += ~"`"; + self.span_fatal(copy self.last_span, s); + } return iovi_none; }; } fn parse_item(+attrs: ~[attribute]) -> Option<@ast::item> { - match self.parse_item_or_view_item(attrs, true) { + match self.parse_item_or_view_item(attrs, true, false) { iovi_none => None, iovi_view_item(_) => self.fatal(~"view items are not allowed here"), + iovi_foreign_item(_) => + self.fatal(~"foreign items are not allowed here"), iovi_item(item) => Some(item) } @@ -3492,28 +3514,35 @@ impl Parser { mode: view_item_parse_mode) -> {attrs_remaining: ~[attribute], view_items: ~[@view_item], - items: ~[@item]} { + items: ~[@item], + foreign_items: ~[@foreign_item]} { let mut attrs = vec::append(first_item_attrs, self.parse_outer_attributes()); - let items_allowed; - match mode { - VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => - items_allowed = true, - VIEW_ITEMS_ALLOWED => - items_allowed = false - } + let items_allowed = match mode { + VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => true, + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false + }; - let (view_items, items) = (DVec(), DVec()); + let restricted_to_imports = match mode { + IMPORTS_AND_ITEMS_ALLOWED => true, + VIEW_ITEMS_AND_ITEMS_ALLOWED | + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false + }; + + let foreign_items_allowed = match mode { + VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => true, + VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => false + }; + + let (view_items, items, foreign_items) = (DVec(), DVec(), DVec()); loop { - match self.parse_item_or_view_item(attrs, items_allowed) { + match self.parse_item_or_view_item(attrs, items_allowed, + foreign_items_allowed) { iovi_none => break, iovi_view_item(view_item) => { - match mode { - VIEW_ITEMS_AND_ITEMS_ALLOWED | - VIEW_ITEMS_ALLOWED => {} - IMPORTS_AND_ITEMS_ALLOWED => + if restricted_to_imports { match view_item.node { view_item_import(_) => {} view_item_export(_) | view_item_use(*) => @@ -3528,13 +3557,18 @@ impl Parser { assert items_allowed; items.push(item) } + iovi_foreign_item(foreign_item) => { + assert foreign_items_allowed; + foreign_items.push(foreign_item); + } } attrs = self.parse_outer_attributes(); } {attrs_remaining: attrs, view_items: dvec::unwrap(move view_items), - items: dvec::unwrap(move items)} + items: dvec::unwrap(move items), + foreign_items: dvec::unwrap(move foreign_items)} } // Parses a source module as a crate diff --git a/src/test/compile-fail/duplicate-visibility.rs b/src/test/compile-fail/duplicate-visibility.rs new file mode 100644 index 000000000000..32997fcce31a --- /dev/null +++ b/src/test/compile-fail/duplicate-visibility.rs @@ -0,0 +1,4 @@ +// error-pattern:unmatched visibility `pub` +extern { + pub pub fn foo(); +} From fdd7b4d8f4df135f30a3f04ff2f777bce1277d2a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 17 Oct 2012 16:40:18 -0700 Subject: [PATCH 232/292] core: first working sketch of a condition system. --- src/libcore/condition.rs | 117 +++++++++++++++++++++++++++++++++++++++ src/libcore/core.rc | 1 + 2 files changed, 118 insertions(+) create mode 100644 src/libcore/condition.rs diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs new file mode 100644 index 000000000000..5f61f2cd53b1 --- /dev/null +++ b/src/libcore/condition.rs @@ -0,0 +1,117 @@ +// helper for transmutation, shown below. +type RustClosure = (int,int); + +struct Condition { + key: task::local_data::LocalDataKey +} + +struct Handler { + // Handler should link to previous handler and + // reinstall it when popped. + handle: RustClosure +} + + +struct ProtectBlock { + cond: &Condition, + inner: RustClosure +} + +struct PopHandler { + cond: &Condition, + drop { + unsafe { + task::local_data::local_data_pop(self.cond.key); + } + } +} + +struct HandleBlock { + pb: &ProtectBlock, + handler: @Handler, + drop { + unsafe { + task::local_data::local_data_set(self.pb.cond.key, + self.handler); + let _pop = PopHandler { cond: self.pb.cond }; + // transmutation to avoid copying non-copyable, should + // be fixable by tracking closure pointees in regionck. + let f : &fn() = ::cast::transmute(self.pb.inner); + f(); + } + } +} + +impl ProtectBlock { + fn handle(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self { + unsafe { + let p : *RustClosure = ::cast::transmute(&h); + HandleBlock { pb: self, + handler: @Handler{handle: *p} } + } + } +} + + +impl Condition { + + fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self { + unsafe { + // transmutation to avoid copying non-copyable, should + // be fixable by tracking closure pointees in regionck. + let p : *RustClosure = ::cast::transmute(&inner); + ProtectBlock { cond: self, + inner: *p } } + } + + fn raise(t:&T) -> U { + unsafe { + match task::local_data::local_data_get(self.key) { + None => fail, + Some(handler) => { + io::println("got handler"); + let f : &fn(&T) -> U = ::cast::transmute(handler.handle); + f(t) + } + } + } + } +} + + +#[test] +fn happiness_key(_x: @Handler) { } + +#[test] +fn sadness_key(_x: @Handler) { } + +#[test] +fn trouble(i: int) { + // Condition should work as a const, just limitations in consts. + let sadness_condition : Condition = Condition { key: sadness_key }; + io::println("raising"); + let j = sadness_condition.raise(&i); + io::println(fmt!("handler recovered with %d", j)); +} + +#[test] +fn test() { + + let sadness_condition : Condition = Condition { key: sadness_key }; + + let mut i = 10; + + let b = do sadness_condition.protect { + io::println("in protected block"); + trouble(1); + trouble(2); + trouble(3); + }; + + do b.handle |j| { + i += *j; + i + }; + + assert i == 16; +} \ No newline at end of file diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 484c58750328..9ebdad3521e5 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -200,6 +200,7 @@ pub mod flate; pub mod repr; pub mod cleanup; pub mod reflect; +pub mod condition; // Modules supporting compiler-generated code // Exported but not part of the public interface From 0f2fc71d799eb3a804fc469a381a56cf6311e7a7 Mon Sep 17 00:00:00 2001 From: Paul Stansifer Date: Wed, 17 Oct 2012 21:40:39 -0400 Subject: [PATCH 233/292] Add examples to the parsing limitations section of the macro tutorial. (Thanks to bstrie for pointing them out!) --- doc/tutorial-macros.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/doc/tutorial-macros.md b/doc/tutorial-macros.md index 995944b2fbd8..c7e1ada648e9 100644 --- a/doc/tutorial-macros.md +++ b/doc/tutorial-macros.md @@ -155,17 +155,22 @@ If it is under more, it'll be repeated, as appropriate. ## Parsing limitations -The macro parser will parse Rust syntax with two limitations: -1. The parser will always parse as much as possible. For example, if the comma -were omitted from the syntax of `early_return!` above, `input_1 [` would've -been interpreted as the beginning of an array index. In fact, invoking the -macro would have been impossible. -2. The parser must have eliminated all ambiguity by the time it reaches a +For technical reasons, there are two limitations to the treatment of syntax +fragments by the macro parser: + +1. The parser will always parse as much as possible of a Rust syntactic +fragment. For example, if the comma were omitted from the syntax of +`early_return!` above, `input_1 [` would've been interpreted as the beginning +of an array index. In fact, invoking the macro would have been impossible. +2. The parser must have eliminated all ambiguity by the time it reaches a `$name:fragment_specifier` declaration. This limitation can result in parse errors when declarations occur at the beginning of, or immediately after, -a `$(...)*`. Changing the invocation syntax to require a distinctive -token in front can solve the problem. +a `$(...)*`. For example, the grammar `$($t:ty)* $e:expr` will always fail to +parse because the parser would be forced to choose between parsing `t` and +parsing `e`. Changing the invocation syntax to require a distinctive token in +front can solve the problem. In the above example, `$(T $t:ty)* E $e:exp` +solves the problem. ## A final note From 2c1ed186fc2a4ccfa49d8395fe1aae85b10e402b Mon Sep 17 00:00:00 2001 From: Tony Young Date: Thu, 18 Oct 2012 22:56:22 +1300 Subject: [PATCH 234/292] Check pandoc's version correctly for >=1.10. --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 40c6acead0ef..cd500b6ec43a 100755 --- a/configure +++ b/configure @@ -362,10 +362,10 @@ fi if [ ! -z "$CFG_PANDOC" ] then - PV=$(pandoc --version | awk '/^pandoc/ {print $2}') - if [ "$PV" \< "1.8" ] + read PV_MAJOR PV_MINOR <<<$(pandoc --version | awk '/^pandoc/ {split($2, PV, "."); print PV[1] " " PV[2]}') + if [ "$PV_MAJOR" -lt "1" ] || [ "$PV_MINOR" -lt "8" ] then - step_msg "pandoc $PV is too old. disabling" + step_msg "pandoc $PV_MAJOR.$PV_MINOR is too old. disabling" BAD_PANDOC=1 fi fi From c0cee3ebe47d4fca73cdab23889322c5e47f12e5 Mon Sep 17 00:00:00 2001 From: Tycho Sci Date: Thu, 18 Oct 2012 22:11:03 +0900 Subject: [PATCH 235/292] libcore: Make run::program_output UTF-8 safe --- src/libcore/run.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 06b869306305..cb6a7f737f98 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -248,12 +248,14 @@ pub fn start_program(prog: &str, args: &[~str]) -> Program { } fn read_all(rd: io::Reader) -> ~str { - let mut buf = ~""; - while !rd.eof() { - let bytes = rd.read_bytes(4096u); - buf += str::from_bytes(bytes); - } - move buf + let buf = io::with_bytes_writer(|wr| { + let mut bytes = [mut 0, ..4096]; + while !rd.eof() { + let nread = rd.read(bytes, bytes.len()); + wr.write(bytes.view(0, nread)); + } + }); + str::from_bytes(buf) } /** @@ -341,13 +343,15 @@ fn writeclose(fd: c_int, s: ~str) { fn readclose(fd: c_int) -> ~str { let file = os::fdopen(fd); let reader = io::FILE_reader(file, false); - let mut buf = ~""; - while !reader.eof() { - let bytes = reader.read_bytes(4096u); - buf += str::from_bytes(bytes); - } + let buf = io::with_bytes_writer(|writer| { + let mut bytes = [mut 0, ..4096]; + while !reader.eof() { + let nread = reader.read(bytes, bytes.len()); + writer.write(bytes.view(0, nread)); + } + }); os::fclose(file); - move buf + str::from_bytes(buf) } /// Waits for a process to exit and returns the exit code From 6ce4cf769f671c53f05e97357110d4c0ba322eae Mon Sep 17 00:00:00 2001 From: Tycho Sci Date: Thu, 18 Oct 2012 22:13:01 +0900 Subject: [PATCH 236/292] rustdoc: Make markdown_writer::pandoc_writer UTF-8 safe --- src/rustdoc/markdown_writer.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/rustdoc/markdown_writer.rs b/src/rustdoc/markdown_writer.rs index ea559ae2ee6b..1ed007def633 100644 --- a/src/rustdoc/markdown_writer.rs +++ b/src/rustdoc/markdown_writer.rs @@ -136,13 +136,15 @@ fn readclose(fd: libc::c_int) -> ~str { // Copied from run::program_output let file = os::fdopen(fd); let reader = io::FILE_reader(file, false); - let mut buf = ~""; - while !reader.eof() { - let bytes = reader.read_bytes(4096u); - buf += str::from_bytes(bytes); - } + let buf = io::with_bytes_writer(|writer| { + let mut bytes = [mut 0, ..4096]; + while !reader.eof() { + let nread = reader.read(bytes, bytes.len()); + writer.write(bytes.view(0, nread)); + } + }); os::fclose(file); - return buf; + str::from_bytes(buf) } fn generic_writer(+process: fn~(markdown: ~str)) -> Writer { From 4e03ffdb6547d9541de84b61d7798b497235472b Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 18 Oct 2012 08:03:04 -0700 Subject: [PATCH 237/292] rustc: optimize away some mallocs when building GEP args --- src/rustc/middle/trans/build.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rustc/middle/trans/build.rs b/src/rustc/middle/trans/build.rs index dfcc66adc3ac..ea992600ae19 100644 --- a/src/rustc/middle/trans/build.rs +++ b/src/rustc/middle/trans/build.rs @@ -433,8 +433,7 @@ fn GEP(cx: block, Pointer: ValueRef, Indices: ~[ValueRef]) -> ValueRef { // // XXX: Use a small-vector optimization to avoid allocations here. fn GEPi(cx: block, base: ValueRef, ixs: &[uint]) -> ValueRef { - let mut v: ~[ValueRef] = ~[]; - for vec::each(ixs) |i| { v.push(C_i32(*i as i32)); } + let v = do vec::map(ixs) |i| { C_i32(*i as i32) }; count_insn(cx, "gepi"); return InBoundsGEP(cx, base, v); } From b18a15171bfbcde81c44967a865214389d6fd7ad Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 18 Oct 2012 09:04:47 -0700 Subject: [PATCH 238/292] Make with_bytes_reader/with_bytes_writer pure --- src/libcore/dvec.rs | 2 +- src/libcore/io.rs | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index 1540eb30fe5a..1b6a7522864e 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -56,7 +56,7 @@ pub enum DVec { } /// Creates a new, empty dvec -pub fn DVec() -> DVec { +pub pure fn DVec() -> DVec { DVec_({mut data: ~[]}) } diff --git a/src/libcore/io.rs b/src/libcore/io.rs index fd0fcbbe1c1f..41fc1bb1a69e 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -328,7 +328,7 @@ impl ByteBuf: Reader { fn tell() -> uint { self.pos } } -pub fn with_bytes_reader(bytes: &[u8], f: fn(Reader) -> t) -> t { +pub pure fn with_bytes_reader(bytes: &[u8], f: fn(Reader) -> t) -> t { f({buf: bytes, mut pos: 0u} as Reader) } @@ -730,21 +730,25 @@ impl @BytesWriter : Writer { fn get_type() -> WriterType { (*self).get_type() } } -pub fn BytesWriter() -> BytesWriter { +pub pure fn BytesWriter() -> BytesWriter { BytesWriter { buf: DVec(), mut pos: 0u } } -pub fn with_bytes_writer(f: fn(Writer)) -> ~[u8] { +pub pure fn with_bytes_writer(f: fn(Writer)) -> ~[u8] { let wr = @BytesWriter(); f(wr as Writer); - wr.buf.check_out(|buf| move buf) + // FIXME (#3758): This should not be needed. + unsafe { wr.buf.check_out(|buf| move buf) } } -pub fn with_str_writer(f: fn(Writer)) -> ~str { +pub pure fn with_str_writer(f: fn(Writer)) -> ~str { let mut v = with_bytes_writer(f); - // Make sure the vector has a trailing null and is proper utf8. - v.push(0); + // FIXME (#3758): This should not be needed. + unsafe { + // Make sure the vector has a trailing null and is proper utf8. + v.push(0); + } assert str::is_utf8(v); unsafe { move ::cast::transmute(move v) } From e3b1471acdfe6121a8e0f657d8caa27393703253 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 18 Oct 2012 09:06:53 -0700 Subject: [PATCH 239/292] Rewrite io::ByteBuf into a struct --- src/libcore/io.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 41fc1bb1a69e..676883394af2 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -297,39 +297,41 @@ pub fn file_reader(path: &Path) -> Result { } -// Byte buffer readers +// Byte readers +pub struct BytesReader { + bytes: &[u8], + mut pos: uint +} -pub type ByteBuf = {buf: &[const u8], mut pos: uint}; +impl BytesReader: Reader { + fn read(bytes: &[mut u8], len: uint) -> uint { + let count = uint::min(len, self.bytes.len() - self.pos); -impl ByteBuf: Reader { - fn read(buf: &[mut u8], len: uint) -> uint { - let count = uint::min(len, self.buf.len() - self.pos); - - let view = vec::const_view(self.buf, self.pos, self.buf.len()); - vec::bytes::memcpy(buf, view, count); + let view = vec::view(self.bytes, self.pos, self.bytes.len()); + vec::bytes::memcpy(bytes, view, count); self.pos += count; count } fn read_byte() -> int { - if self.pos == self.buf.len() { return -1; } - let b = self.buf[self.pos]; + if self.pos == self.bytes.len() { return -1; } + let b = self.bytes[self.pos]; self.pos += 1u; return b as int; } // FIXME (#2738): implement this fn unread_byte(_byte: int) { error!("Unimplemented: unread_byte"); fail; } - fn eof() -> bool { self.pos == self.buf.len() } + fn eof() -> bool { self.pos == self.bytes.len() } fn seek(offset: int, whence: SeekStyle) { let pos = self.pos; - self.pos = seek_in_buf(offset, pos, self.buf.len(), whence); + self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence); } fn tell() -> uint { self.pos } } pub pure fn with_bytes_reader(bytes: &[u8], f: fn(Reader) -> t) -> t { - f({buf: bytes, mut pos: 0u} as Reader) + f(BytesReader { bytes: bytes, pos: 0u } as Reader) } pub fn with_str_reader(s: &str, f: fn(Reader) -> T) -> T { From 95423d28f221ac67bad7e7c6396b983705a056ae Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 18 Oct 2012 09:10:37 -0700 Subject: [PATCH 240/292] libcore: call [u8] values bytes, not bufs --- src/libcore/io.rs | 96 ++++++++++++++++++----------------- src/rustc/metadata/encoder.rs | 4 +- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 676883394af2..92315285d043 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -37,7 +37,7 @@ pub trait Reader { // FIXME (#2004): Seekable really should be orthogonal. // FIXME (#2982): This should probably return an error. - fn read(buf: &[mut u8], len: uint) -> uint; + fn read(bytes: &[mut u8], len: uint) -> uint; fn read_byte() -> int; fn unread_byte(int); fn eof() -> bool; @@ -65,32 +65,32 @@ pub trait ReaderUtil { impl T : ReaderUtil { fn read_bytes(len: uint) -> ~[u8] { - let mut buf = vec::with_capacity(len); - unsafe { vec::raw::set_len(&mut buf, len); } + let mut bytes = vec::with_capacity(len); + unsafe { vec::raw::set_len(&mut bytes, len); } - let count = self.read(buf, len); + let count = self.read(bytes, len); - unsafe { vec::raw::set_len(&mut buf, count); } - move buf + unsafe { vec::raw::set_len(&mut bytes, count); } + move bytes } fn read_line() -> ~str { - let mut buf = ~[]; + let mut bytes = ~[]; loop { let ch = self.read_byte(); if ch == -1 || ch == 10 { break; } - buf.push(ch as u8); + bytes.push(ch as u8); } - str::from_bytes(buf) + str::from_bytes(bytes) } fn read_chars(n: uint) -> ~[char] { // returns the (consumed offset, n_req), appends characters to &chars - fn chars_from_bytes(buf: &~[u8], chars: &mut ~[char]) + fn chars_from_bytes(bytes: &~[u8], chars: &mut ~[char]) -> (uint, uint) { let mut i = 0; - let buf_len = buf.len(); - while i < buf_len { - let b0 = buf[i]; + let bytes_len = bytes.len(); + while i < bytes_len { + let b0 = bytes[i]; let w = str::utf8_char_width(b0); let end = i + w; i += 1; @@ -100,12 +100,12 @@ impl T : ReaderUtil { loop; } // can't satisfy this char with the existing data - if end > buf_len { - return (i - 1, end - buf_len); + if end > bytes_len { + return (i - 1, end - bytes_len); } let mut val = 0; while i < end { - let next = buf[i] as int; + let next = bytes[i] as int; i += 1; assert (next > -1); assert (next & 192 == 128); @@ -119,7 +119,7 @@ impl T : ReaderUtil { } return (i, 0); } - let mut buf: ~[u8] = ~[]; + let mut bytes: ~[u8] = ~[]; let mut chars: ~[char] = ~[]; // might need more bytes, but reading n will never over-read let mut nbread = n; @@ -130,15 +130,15 @@ impl T : ReaderUtil { // we're split in a unicode char? break; } - buf.push_all(data); - let (offset, nbreq) = chars_from_bytes::(&buf, &mut chars); + bytes.push_all(data); + let (offset, nbreq) = chars_from_bytes::(&bytes, &mut chars); let ncreq = n - chars.len(); // again we either know we need a certain number of bytes // to complete a character, or we make sure we don't // over-read by reading 1-byte per char needed nbread = if ncreq > nbreq { ncreq } else { nbreq }; if nbread > 0 { - buf = vec::slice(buf, offset, buf.len()); + bytes = vec::slice(bytes, offset, bytes.len()); } } move chars @@ -154,12 +154,12 @@ impl T : ReaderUtil { } fn read_c_str() -> ~str { - let mut buf: ~[u8] = ~[]; + let mut bytes: ~[u8] = ~[]; loop { let ch = self.read_byte(); - if ch < 1 { break; } else { buf.push(ch as u8); } + if ch < 1 { break; } else { bytes.push(ch as u8); } } - str::from_bytes(buf) + str::from_bytes(bytes) } // FIXME deal with eof? // #2004 @@ -191,9 +191,9 @@ impl T : ReaderUtil { } fn read_whole_stream() -> ~[u8] { - let mut buf: ~[u8] = ~[]; - while !self.eof() { buf.push_all(self.read_bytes(2048u)); } - move buf + let mut bytes: ~[u8] = ~[]; + while !self.eof() { bytes.push_all(self.read_bytes(2048u)); } + move bytes } fn each_byte(it: fn(int) -> bool) { @@ -226,8 +226,8 @@ fn convert_whence(whence: SeekStyle) -> i32 { } impl *libc::FILE: Reader { - fn read(buf: &[mut u8], len: uint) -> uint { - do vec::as_mut_buf(buf) |buf_p, buf_len| { + fn read(bytes: &[mut u8], len: uint) -> uint { + do vec::as_mut_buf(bytes) |buf_p, buf_len| { assert buf_len <= len; let count = libc::fread(buf_p as *mut c_void, 1u as size_t, @@ -250,7 +250,9 @@ impl *libc::FILE: Reader { // duration of its lifetime. // FIXME there really should be a better way to do this // #2004 impl {base: T, cleanup: C}: Reader { - fn read(buf: &[mut u8], len: uint) -> uint { self.base.read(buf, len) } + fn read(bytes: &[mut u8], len: uint) -> uint { + self.base.read(bytes, len) + } fn read_byte() -> int { self.base.read_byte() } fn unread_byte(byte: int) { self.base.unread_byte(byte); } fn eof() -> bool { self.base.eof() } @@ -604,10 +606,10 @@ impl T : WriterUtil { self.write_str(&"\n"); } fn write_int(n: int) { - int::to_str_bytes(n, 10u, |buf| self.write(buf)) + int::to_str_bytes(n, 10u, |bytes| self.write(bytes)) } fn write_uint(n: uint) { - uint::to_str_bytes(false, n, 10u, |buf| self.write(buf)) + uint::to_str_bytes(false, n, 10u, |bytes| self.write(bytes)) } fn write_le_uint(n: uint) { u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v)) @@ -689,34 +691,34 @@ pub fn print(s: &str) { stdout().write_str(s); } pub fn println(s: &str) { stdout().write_line(s); } pub struct BytesWriter { - buf: DVec, + bytes: DVec, mut pos: uint, } impl BytesWriter: Writer { fn write(v: &[const u8]) { - do self.buf.swap |buf| { - let mut buf <- buf; + do self.bytes.swap |bytes| { + let mut bytes <- bytes; let v_len = v.len(); - let buf_len = buf.len(); + let bytes_len = bytes.len(); - let count = uint::max(buf_len, self.pos + v_len); - vec::reserve(&mut buf, count); - unsafe { vec::raw::set_len(&mut buf, count); } + let count = uint::max(bytes_len, self.pos + v_len); + vec::reserve(&mut bytes, count); + unsafe { vec::raw::set_len(&mut bytes, count); } { - let view = vec::mut_view(buf, self.pos, count); + let view = vec::mut_view(bytes, self.pos, count); vec::bytes::memcpy(view, v, v_len); } self.pos += v_len; - move buf + move bytes } } fn seek(offset: int, whence: SeekStyle) { let pos = self.pos; - let len = self.buf.len(); + let len = self.bytes.len(); self.pos = seek_in_buf(offset, pos, len, whence); } fn tell() -> uint { self.pos } @@ -733,14 +735,14 @@ impl @BytesWriter : Writer { } pub pure fn BytesWriter() -> BytesWriter { - BytesWriter { buf: DVec(), mut pos: 0u } + BytesWriter { bytes: DVec(), mut pos: 0u } } pub pure fn with_bytes_writer(f: fn(Writer)) -> ~[u8] { let wr = @BytesWriter(); f(wr as Writer); // FIXME (#3758): This should not be needed. - unsafe { wr.buf.check_out(|buf| move buf) } + unsafe { wr.bytes.check_out(|bytes| move bytes) } } pub pure fn with_str_writer(f: fn(Writer)) -> ~str { @@ -981,15 +983,17 @@ mod tests { fn bytes_buffer_overwrite() { let wr = BytesWriter(); wr.write(~[0u8, 1u8, 2u8, 3u8]); - assert wr.buf.borrow(|buf| buf == ~[0u8, 1u8, 2u8, 3u8]); + assert wr.bytes.borrow(|bytes| bytes == ~[0u8, 1u8, 2u8, 3u8]); wr.seek(-2, SeekCur); wr.write(~[4u8, 5u8, 6u8, 7u8]); - assert wr.buf.borrow(|buf| buf == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]); + assert wr.bytes.borrow(|bytes| bytes == + ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]); wr.seek(-2, SeekEnd); wr.write(~[8u8]); wr.seek(1, SeekSet); wr.write(~[9u8]); - assert wr.buf.borrow(|buf| buf == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]); + assert wr.bytes.borrow(|bytes| bytes == + ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]); } } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 0b25f0670b42..1579705dd0ec 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -1162,7 +1162,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { if (parms.tcx.sess.meta_stats()) { - do wr.buf.borrow |v| { + do wr.bytes.borrow |v| { do v.each |e| { if *e == 0 { ecx.stats.zero_bytes += 1; @@ -1195,7 +1195,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { (do str::as_bytes(&~"rust\x00\x00\x00\x01") |bytes| { vec::slice(*bytes, 0, 8) - }) + flate::deflate_bytes(wr.buf.check_out(|buf| buf)) + }) + flate::deflate_bytes(wr.bytes.check_out(|buf| buf)) } // Get the encoded string for a type From a7ecde33238f46ae473ceb63db95068f1ce6cffd Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 18 Oct 2012 09:14:11 -0700 Subject: [PATCH 241/292] libcore: minor code cleanup. This is minor and probably completely inconsequential to performance, but I find vec::map to be more clear than vec::each and a push. --- src/libcore/io.rs | 4 ++-- src/libcore/logging.rs | 2 +- src/libcore/repr.rs | 2 +- src/libsyntax/attr.rs | 4 +--- src/rustc/back/upcall.rs | 3 +-- src/rustc/metadata/decoder.rs | 13 ++++++------- src/rustc/util/common.rs | 4 +--- src/rustc/util/ppaux.rs | 9 +++------ 8 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 92315285d043..77f7b5023dfa 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -119,8 +119,8 @@ impl T : ReaderUtil { } return (i, 0); } - let mut bytes: ~[u8] = ~[]; - let mut chars: ~[char] = ~[]; + let mut bytes = ~[]; + let mut chars = ~[]; // might need more bytes, but reading n will never over-read let mut nbread = n; while nbread > 0 { diff --git a/src/libcore/logging.rs b/src/libcore/logging.rs index d4f3c0ea272e..958d1ac56ea7 100644 --- a/src/libcore/logging.rs +++ b/src/libcore/logging.rs @@ -32,7 +32,7 @@ pub fn console_off() { #[cfg(notest)] #[lang="log_type"] pub fn log_type(level: u32, object: &T) { - let bytes = do io::with_bytes_writer() |writer| { + let bytes = do io::with_bytes_writer |writer| { repr::write_repr(writer, object); }; unsafe { diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index ff29953f09a4..b246adcb1d7c 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -559,7 +559,7 @@ impl ReprPrinter { unsafe { self.align(sys::min_align_of::()); let value_addr: &T = transmute(copy self.ptr); - (*value_addr).write_repr(self.writer); + value_addr.write_repr(self.writer); self.bump(sys::size_of::()); true } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index d08edd7af1d0..4bd1679600ff 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -90,9 +90,7 @@ fn attr_meta(attr: ast::attribute) -> @ast::meta_item { @attr.node.value } // Get the meta_items from inside a vector of attributes fn attr_metas(attrs: ~[ast::attribute]) -> ~[@ast::meta_item] { - let mut mitems = ~[]; - for attrs.each |a| { mitems.push(attr_meta(*a)); } - return mitems; + do attrs.map |a| { attr_meta(*a) } } fn desugar_doc_attr(attr: &ast::attribute) -> ast::attribute { diff --git a/src/rustc/back/upcall.rs b/src/rustc/back/upcall.rs index a2c864f6f465..45e7cd4e9d45 100644 --- a/src/rustc/back/upcall.rs +++ b/src/rustc/back/upcall.rs @@ -27,8 +27,7 @@ fn declare_upcalls(targ_cfg: @session::config, fn decl(llmod: ModuleRef, prefix: ~str, name: ~str, tys: ~[TypeRef], rv: TypeRef) -> ValueRef { - let mut arg_tys: ~[TypeRef] = ~[]; - for tys.each |t| { arg_tys.push(*t); } + let arg_tys = tys.map(|t| *t); let fn_ty = T_fn(arg_tys, rv); return base::decl_cdecl_fn(llmod, prefix + name, fn_ty); } diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index f0911bd1aa27..1656efbd9668 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -598,13 +598,12 @@ fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id, let ctor_ty = item_type({crate: cdata.cnum, node: id}, item, tcx, cdata); let name = item_name(intr, item); - let mut arg_tys: ~[ty::t] = ~[]; - match ty::get(ctor_ty).sty { - ty::ty_fn(f) => { - for f.sig.inputs.each |a| { arg_tys.push(a.ty); } - } - _ => { /* Nullary enum variant. */ } - } + let arg_tys = match ty::get(ctor_ty).sty { + ty::ty_fn(f) => f.sig.inputs.map(|a| a.ty), + + // Nullary enum variant. + _ => ~[], + }; match variant_disr_val(item) { Some(val) => { disr_val = val; } _ => { /* empty */ } diff --git a/src/rustc/util/common.rs b/src/rustc/util/common.rs index 0c6ec267da81..123905adba11 100644 --- a/src/rustc/util/common.rs +++ b/src/rustc/util/common.rs @@ -34,9 +34,7 @@ type flag = HashMap<~str, ()>; fn field_expr(f: ast::field) -> @ast::expr { return f.node.expr; } fn field_exprs(fields: ~[ast::field]) -> ~[@ast::expr] { - let mut es = ~[]; - for fields.each |f| { es.push(f.node.expr); } - return es; + fields.map(|f| f.node.expr) } // Takes a predicate p, returns true iff p is true for any subexpressions diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index 27ace283fa0c..8207082cf20e 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -282,8 +282,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { _ => { } } s += ~"("; - let mut strs = ~[]; - for inputs.each |a| { strs.push(fn_input_to_str(cx, *a)); } + let strs = inputs.map(|a| fn_input_to_str(cx, *a)); s += str::connect(strs, ~", "); s += ~")"; if ty::get(output).sty != ty_nil { @@ -338,13 +337,11 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_unboxed_vec(tm) => { ~"unboxed_vec<" + mt_to_str(cx, tm) + ~">" } ty_type => ~"type", ty_rec(elems) => { - let mut strs: ~[~str] = ~[]; - for elems.each |fld| { strs.push(field_to_str(cx, *fld)); } + let strs = elems.map(|fld| field_to_str(cx, *fld)); ~"{" + str::connect(strs, ~",") + ~"}" } ty_tup(elems) => { - let mut strs = ~[]; - for elems.each |elem| { strs.push(ty_to_str(cx, *elem)); } + let strs = elems.map(|elem| ty_to_str(cx, *elem)); ~"(" + str::connect(strs, ~",") + ~")" } ty_fn(ref f) => { From ac50046a111a1ef6fb58b7e5f368ff6b9b55f89c Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 18 Oct 2012 11:04:32 -0700 Subject: [PATCH 242/292] Simplify str::to_managed --- src/libcore/str.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d59f36e06813..d32d35cbe1a4 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2262,9 +2262,8 @@ impl &str: StrSlice { #[inline] pure fn to_managed() -> @str { - let v = at_vec::from_fn(self.len() + 1, |i| { - if i == self.len() { 0 } else { self[i] } - }); + let bytes = as_bytes_slice(self); + let v = at_vec::from_fn(bytes.len(), |i| bytes[i]); unsafe { ::cast::transmute(v) } } From fe41ccec6440b6ae64cae26da8e9bc42e1b06a9f Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 18 Oct 2012 11:04:59 -0700 Subject: [PATCH 243/292] Rename str::to_unique to str::to_owned. --- src/libcore/extfmt.rs | 4 ++-- src/libcore/option.rs | 2 +- src/libcore/str.rs | 4 ++-- src/libstd/json.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/extfmt.rs b/src/libcore/extfmt.rs index 5acb45fdf1a5..d41393c23934 100644 --- a/src/libcore/extfmt.rs +++ b/src/libcore/extfmt.rs @@ -329,11 +329,11 @@ pub mod rt { // For strings, precision is the maximum characters // displayed let mut unpadded = match cv.precision { - CountImplied => s.to_unique(), + CountImplied => s.to_owned(), CountIs(max) => if max as uint < str::char_len(s) { str::substr(s, 0u, max as uint) } else { - s.to_unique() + s.to_owned() } }; return unsafe { pad(cv, move unpadded, PadNozero) }; diff --git a/src/libcore/option.rs b/src/libcore/option.rs index f8bafe29fdde..50489a820291 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -225,7 +225,7 @@ pub fn swap_unwrap(opt: &mut Option) -> T { pub pure fn unwrap_expect(opt: Option, reason: &str) -> T { //! As unwrap, but with a specified failure message. - if opt.is_none() { fail reason.to_unique(); } + if opt.is_none() { fail reason.to_owned(); } unwrap(move opt) } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d32d35cbe1a4..3122f3d7f32e 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2135,7 +2135,7 @@ pub trait StrSlice { pure fn trim() -> ~str; pure fn trim_left() -> ~str; pure fn trim_right() -> ~str; - pure fn to_unique() -> ~str; + pure fn to_owned() -> ~str; pure fn to_managed() -> @str; pure fn char_at(i: uint) -> char; } @@ -2258,7 +2258,7 @@ impl &str: StrSlice { pure fn trim_right() -> ~str { trim_right(self) } #[inline] - pure fn to_unique() -> ~str { self.slice(0, self.len()) } + pure fn to_owned() -> ~str { self.slice(0, self.len()) } #[inline] pure fn to_managed() -> @str { diff --git a/src/libstd/json.rs b/src/libstd/json.rs index d170255b565d..5f64389e5832 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -897,7 +897,7 @@ pub impl Deserializer: serialization::Deserializer { // FIXME(#3148) This hint should not be necessary. let obj: &self/~Object = obj; - match obj.find_ref(&name.to_unique()) { + match obj.find_ref(&name.to_owned()) { None => fail fmt!("no such field: %s", name), Some(json) => { self.stack.push(json); From fa38c1290119c1ceca77db38c0075f7412d296d7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 18 Oct 2012 12:08:52 -0700 Subject: [PATCH 244/292] test: Fix failing tests. r=rustbot --- src/test/compile-fail/issue-2766-a.rs | 10 +++++----- src/test/compile-fail/issue-3099-a.rs | 2 +- src/test/compile-fail/issue-3099-b.rs | 2 +- src/test/compile-fail/issue-3099.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/compile-fail/issue-2766-a.rs b/src/test/compile-fail/issue-2766-a.rs index 75e524e27ac4..590ea5e0b7cc 100644 --- a/src/test/compile-fail/issue-2766-a.rs +++ b/src/test/compile-fail/issue-2766-a.rs @@ -1,13 +1,13 @@ mod stream { #[legacy_exports]; - enum stream { send(T, server::stream), } + enum Stream { send(T, server::Stream), } mod server { #[legacy_exports]; - impl stream { - fn recv() -> extern fn(+v: stream) -> stream::stream { + impl Stream { + fn recv() -> extern fn(+v: Stream) -> stream::Stream { // resolve really should report just one error here. // Change the test case when it changes. - fn recv(+pipe: stream) -> stream::stream { //~ ERROR attempt to use a type argument out of scope + fn recv(+pipe: Stream) -> stream::Stream { //~ ERROR attempt to use a type argument out of scope //~^ ERROR use of undeclared type name //~^^ ERROR attempt to use a type argument out of scope //~^^^ ERROR use of undeclared type name @@ -16,7 +16,7 @@ mod stream { recv } } - type stream = pipes::RecvPacket>; + type Stream = pipes::RecvPacket>; } } diff --git a/src/test/compile-fail/issue-3099-a.rs b/src/test/compile-fail/issue-3099-a.rs index 2721186585bc..fee676ed5e28 100644 --- a/src/test/compile-fail/issue-3099-a.rs +++ b/src/test/compile-fail/issue-3099-a.rs @@ -1,5 +1,5 @@ enum a { b, c } -enum a { d, e } //~ ERROR Duplicate definition of type a +enum a { d, e } //~ ERROR duplicate definition of type a fn main() {} diff --git a/src/test/compile-fail/issue-3099-b.rs b/src/test/compile-fail/issue-3099-b.rs index 997bb9e25571..dc393eb75207 100644 --- a/src/test/compile-fail/issue-3099-b.rs +++ b/src/test/compile-fail/issue-3099-b.rs @@ -2,6 +2,6 @@ mod a {} #[legacy_exports] -mod a {} //~ ERROR Duplicate definition of module a +mod a {} //~ ERROR duplicate definition of type a fn main() {} diff --git a/src/test/compile-fail/issue-3099.rs b/src/test/compile-fail/issue-3099.rs index d5c016c1ea87..79212686130a 100644 --- a/src/test/compile-fail/issue-3099.rs +++ b/src/test/compile-fail/issue-3099.rs @@ -2,7 +2,7 @@ fn a(x: ~str) -> ~str { fmt!("First function with %s", x) } -fn a(x: ~str, y: ~str) -> ~str { //~ ERROR Duplicate definition of value a +fn a(x: ~str, y: ~str) -> ~str { //~ ERROR duplicate definition of value a fmt!("Second function with %s and %s", x, y) } From b03c71f6297304d40b22583750d288e3c215ca79 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 18 Oct 2012 12:09:44 -0700 Subject: [PATCH 245/292] Remove dead type definition --- src/libsyntax/ast.rs | 4 ---- src/libsyntax/parse/parser.rs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e3da15d181b7..454a3166898b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -749,10 +749,6 @@ type expr = {id: node_id, callee_id: node_id, node: expr_, span: span}; enum log_level { error, debug, other } // 0 = error, 1 = debug, 2 = other -#[auto_serialize] -#[auto_deserialize] -enum alt_mode { alt_check, alt_exhaustive, } - #[auto_serialize] #[auto_deserialize] enum expr_ { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index cbad662800b5..8636c51b369d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -22,7 +22,7 @@ use obsolete::{ ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits, ObsoleteModeInFnType, ObsoleteByMutRefMode }; -use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, +use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move, bitand, bitor, bitxor, blk, blk_check_mode, bound_const, bound_copy, bound_send, bound_trait, bound_owned, box, by_copy, From eeae55208cfc393d6886e9b7a94d14f99e9bd7b8 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 18 Oct 2012 11:53:27 -0700 Subject: [PATCH 246/292] Revert "Simplify str::to_managed" This reverts commit ac50046a111a1ef6fb58b7e5f368ff6b9b55f89c. --- src/libcore/str.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 3122f3d7f32e..3da41ac6abc8 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2262,8 +2262,9 @@ impl &str: StrSlice { #[inline] pure fn to_managed() -> @str { - let bytes = as_bytes_slice(self); - let v = at_vec::from_fn(bytes.len(), |i| bytes[i]); + let v = at_vec::from_fn(self.len() + 1, |i| { + if i == self.len() { 0 } else { self[i] } + }); unsafe { ::cast::transmute(v) } } From 754704ea9442ce92602f8022f6c979824b016842 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 18 Oct 2012 13:29:34 -0700 Subject: [PATCH 247/292] rustc: Implement intra-crate static methods on anonymous trait implementations. r=nmatsakis --- src/libsyntax/ast.rs | 30 +---- src/libsyntax/codemap.rs | 32 +++++ src/rustc/metadata/common.rs | 2 + src/rustc/metadata/csearch.rs | 21 ++++ src/rustc/metadata/decoder.rs | 83 +++++++++++-- src/rustc/metadata/encoder.rs | 22 +++- src/rustc/middle/astencode.rs | 6 +- src/rustc/middle/resolve.rs | 110 +++++++++++++++--- src/rustc/middle/trans/callee.rs | 4 +- src/rustc/middle/trans/expr.rs | 4 +- .../auxiliary/anon_trait_static_method_lib.rs | 10 ++ .../run-pass/anon_trait_static_method_exe.rs | 13 +++ 12 files changed, 276 insertions(+), 61 deletions(-) create mode 100644 src/test/auxiliary/anon_trait_static_method_lib.rs create mode 100644 src/test/run-pass/anon_trait_static_method_exe.rs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 454a3166898b..f494d5648168 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -7,34 +7,6 @@ use std::serialization::{Serializable, use codemap::{span, filename}; use parse::token; -#[cfg(stage0)] -impl span: Serializable { - /* Note #1972 -- spans are serialized but not deserialized */ - fn serialize(&self, _s: &S) { } -} - -#[cfg(stage0)] -impl span: Deserializable { - static fn deserialize(_d: &D) -> span { - ast_util::dummy_sp() - } -} - -#[cfg(stage1)] -#[cfg(stage2)] -impl span: Serializable { - /* Note #1972 -- spans are serialized but not deserialized */ - fn serialize(&self, _s: &S) { } -} - -#[cfg(stage1)] -#[cfg(stage2)] -impl span: Deserializable { - static fn deserialize(_d: &D) -> span { - ast_util::dummy_sp() - } -} - #[auto_serialize] #[auto_deserialize] type spanned = {node: T, span: span}; @@ -168,7 +140,7 @@ type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; enum def { def_fn(def_id, purity), def_static_method(/* method */ def_id, - /* trait */ def_id, + /* trait */ Option, purity), def_self(node_id), def_mod(def_id), diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 0cb8b425c942..69a80d0bac13 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -1,4 +1,8 @@ use dvec::DVec; +use std::serialization::{Serializable, + Deserializable, + Serializer, + Deserializer}; export filename; export filemap; @@ -178,6 +182,34 @@ impl span : cmp::Eq { pure fn ne(other: &span) -> bool { !self.eq(other) } } +#[cfg(stage0)] +impl span: Serializable { + /* Note #1972 -- spans are serialized but not deserialized */ + fn serialize(&self, _s: &S) { } +} + +#[cfg(stage0)] +impl span: Deserializable { + static fn deserialize(_d: &D) -> span { + ast_util::dummy_sp() + } +} + +#[cfg(stage1)] +#[cfg(stage2)] +impl span: Serializable { + /* Note #1972 -- spans are serialized but not deserialized */ + fn serialize(&self, _s: &S) { } +} + +#[cfg(stage1)] +#[cfg(stage2)] +impl span: Deserializable { + static fn deserialize(_d: &D) -> span { + ast_util::dummy_sp() + } +} + fn span_to_str_no_adj(sp: span, cm: CodeMap) -> ~str { let lo = lookup_char_pos(cm, sp.lo); let hi = lookup_char_pos(cm, sp.hi); diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs index 972d48a61353..06f1dfdab1aa 100644 --- a/src/rustc/metadata/common.rs +++ b/src/rustc/metadata/common.rs @@ -126,5 +126,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f const tag_item_trait_method_sort: uint = 0x70; +const tag_item_impl_type_basename: uint = 0x71; + type link_meta = {name: ~str, vers: ~str, extras_hash: ~str}; diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index d9fccb16de02..141613c2240d 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -25,6 +25,8 @@ export get_impls_for_mod; export get_trait_methods; export get_provided_trait_methods; export get_method_names_if_trait; +export get_type_name_if_impl; +export get_static_methods_if_impl; export get_item_attrs; export each_path; export get_type; @@ -33,12 +35,19 @@ export get_impl_method; export get_item_path; export maybe_get_item_ast, found_ast, found, found_parent, not_found; export ProvidedTraitMethodInfo; +export StaticMethodInfo; struct ProvidedTraitMethodInfo { ty: ty::method, def_id: ast::def_id } +struct StaticMethodInfo { + ident: ast::ident, + def_id: ast::def_id, + purity: ast::purity +} + fn get_symbol(cstore: cstore::CStore, def: ast::def_id) -> ~str { let cdata = cstore::get_crate_data(cstore, def.crate).data; return decoder::get_symbol(cdata, def.node); @@ -120,6 +129,18 @@ fn get_method_names_if_trait(cstore: cstore::CStore, def: ast::def_id) return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node); } +fn get_type_name_if_impl(cstore: cstore::CStore, def: ast::def_id) -> + Option { + let cdata = cstore::get_crate_data(cstore, def.crate); + decoder::get_type_name_if_impl(cstore.intr, cdata, def.node) +} + +fn get_static_methods_if_impl(cstore: cstore::CStore, def: ast::def_id) -> + Option<~[StaticMethodInfo]> { + let cdata = cstore::get_crate_data(cstore, def.crate); + decoder::get_static_methods_if_impl(cstore.intr, cdata, def.node) +} + fn get_item_attrs(cstore: cstore::CStore, def_id: ast::def_id, f: fn(~[@ast::meta_item])) { diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 1656efbd9668..4e30132b1a73 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -19,7 +19,7 @@ use syntax::diagnostic::span_handler; use common::*; use syntax::parse::token::ident_interner; use hash::{Hash, HashUtil}; -use csearch::ProvidedTraitMethodInfo; +use csearch::{ProvidedTraitMethodInfo, StaticMethodInfo}; export class_dtor; export get_class_fields; @@ -31,6 +31,7 @@ export get_type_param_count; export get_impl_traits; export get_class_method; export get_impl_method; +export get_static_methods_if_impl; export lookup_def; export resolve_path; export get_crate_attributes; @@ -43,6 +44,7 @@ export get_impls_for_mod; export get_trait_methods; export get_provided_trait_methods; export get_method_names_if_trait; +export get_type_name_if_impl; export get_item_attrs; export get_crate_module_paths; export def_like; @@ -185,6 +187,12 @@ fn item_parent_item(d: ebml::Doc) -> Option { None } +fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) -> + Option { + let trait_did_opt = item_parent_item(d); + trait_did_opt.map(|trait_did| {crate: cnum, node: trait_did.node}) +} + fn item_reqd_and_translated_parent_item(cnum: ast::crate_num, d: ebml::Doc) -> ast::def_id { let trait_did = item_parent_item(d).expect(~"item without parent"); @@ -321,16 +329,16 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), UnsafeStaticMethod => { - let trait_did = item_reqd_and_translated_parent_item(cnum, item); - dl_def(ast::def_static_method(did, trait_did, ast::unsafe_fn)) + let trait_did_opt = translated_parent_item_opt(cnum, item); + dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn)) } StaticMethod => { - let trait_did = item_reqd_and_translated_parent_item(cnum, item); - dl_def(ast::def_static_method(did, trait_did, ast::impure_fn)) + let trait_did_opt = translated_parent_item_opt(cnum, item); + dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn)) } PureStaticMethod => { - let trait_did = item_reqd_and_translated_parent_item(cnum, item); - dl_def(ast::def_static_method(did, trait_did, ast::pure_fn)) + let trait_did_opt = translated_parent_item_opt(cnum, item); + dl_def(ast::def_static_method(did, trait_did_opt, ast::pure_fn)) } Type | ForeignType => dl_def(ast::def_ty(did)), Mod => dl_def(ast::def_mod(did)), @@ -783,6 +791,67 @@ fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd, return Some(resulting_methods); } +fn get_type_name_if_impl(intr: @ident_interner, + cdata: cmd, + node_id: ast::node_id) -> Option { + let item = lookup_item(node_id, cdata.data); + if item_family(item) != Impl { + return None; + } + + for ebml::tagged_docs(item, tag_item_impl_type_basename) |doc| { + return Some(intr.intern(@str::from_bytes(ebml::doc_data(doc)))); + } + + return None; +} + +fn get_static_methods_if_impl(intr: @ident_interner, + cdata: cmd, + node_id: ast::node_id) -> + Option<~[StaticMethodInfo]> { + let item = lookup_item(node_id, cdata.data); + if item_family(item) != Impl { + return None; + } + + // If this impl has a trait ref, don't consider it. + for ebml::tagged_docs(item, tag_impl_trait) |_doc| { + return None; + } + + let impl_method_ids = DVec(); + for ebml::tagged_docs(item, tag_item_impl_method) |impl_method_doc| { + impl_method_ids.push(parse_def_id(ebml::doc_data(impl_method_doc))); + } + + let static_impl_methods = DVec(); + for impl_method_ids.each |impl_method_id| { + let impl_method_doc = lookup_item(impl_method_id.node, cdata.data); + let family = item_family(impl_method_doc); + match family { + StaticMethod | UnsafeStaticMethod | PureStaticMethod => { + let purity; + match item_family(impl_method_doc) { + StaticMethod => purity = ast::impure_fn, + UnsafeStaticMethod => purity = ast::unsafe_fn, + PureStaticMethod => purity = ast::pure_fn, + _ => fail + } + + static_impl_methods.push(StaticMethodInfo { + ident: item_name(intr, impl_method_doc), + def_id: item_def_id(impl_method_doc, cdata), + purity: purity + }); + } + _ => {} + } + } + + return Some(dvec::unwrap(move static_impl_methods)); +} + fn get_item_attrs(cdata: cmd, node_id: ast::node_id, f: fn(~[@ast::meta_item])) { diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 1579705dd0ec..a1d85a63ee14 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -90,6 +90,12 @@ fn encode_name(ecx: @encode_ctxt, ebml_w: ebml::Serializer, name: ident) { ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name)); } +fn encode_impl_type_basename(ecx: @encode_ctxt, ebml_w: ebml::Serializer, + name: ident) { + ebml_w.wr_tagged_str(tag_item_impl_type_basename, + ecx.tcx.sess.str_of(name)); +} + fn encode_def_id(ebml_w: ebml::Serializer, id: def_id) { ebml_w.wr_tagged_str(tag_def_id, def_to_str(id)); } @@ -484,7 +490,12 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::Serializer, ecx.tcx.sess.str_of(m.ident), all_tps.len()); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(m.id)); - encode_family(ebml_w, purity_fn_family(m.purity)); + match m.self_ty.node { + ast::sty_static => { + encode_family(ebml_w, purity_static_method_family(m.purity)); + } + _ => encode_family(ebml_w, purity_fn_family(m.purity)) + } encode_type_param_bounds(ebml_w, ecx, all_tps); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id)); encode_name(ecx, ebml_w, m.ident); @@ -701,7 +712,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, encode_index(ebml_w, bkts, write_int); ebml_w.end_tag(); } - item_impl(tps, opt_trait, _, methods) => { + item_impl(tps, opt_trait, ty, methods) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); @@ -711,6 +722,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); + match ty.node { + ast::ty_path(path, _) if path.idents.len() == 1 => { + encode_impl_type_basename(ecx, ebml_w, + ast_util::path_to_ident(path)); + } + _ => {} + } for methods.each |m| { ebml_w.start_tag(tag_item_impl_method); ebml_w.writer.write(str::to_bytes(def_to_str(local_def(m.id)))); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index b47e6d3b151c..d264188e65d3 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -326,8 +326,10 @@ impl ast::def: tr { fn tr(xcx: extended_decode_ctxt) -> ast::def { match self { ast::def_fn(did, p) => { ast::def_fn(did.tr(xcx), p) } - ast::def_static_method(did, did2, p) => { - ast::def_static_method(did.tr(xcx), did2.tr(xcx), p) + ast::def_static_method(did, did2_opt, p) => { + ast::def_static_method(did.tr(xcx), + did2_opt.map(|did2| did2.tr(xcx)), + p) } ast::def_self(nid) => { ast::def_self(xcx.tr_id(nid)) } ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index f522cca7a995..33b56d7fabe0 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -1,5 +1,6 @@ use driver::session::Session; use metadata::csearch::{each_path, get_method_names_if_trait}; +use metadata::csearch::{get_static_methods_if_impl, get_type_name_if_impl}; use metadata::cstore::find_use_stmt_cnum; use metadata::decoder::{def_like, dl_def, dl_field, dl_impl}; use middle::lang_items::LanguageItems; @@ -1082,7 +1083,6 @@ impl Resolver { fn build_reduced_graph_for_item(item: @item, parent: ReducedGraphParent, &&visitor: vt) { - let ident = item.ident; let sp = item.span; let legacy = match parent { @@ -1276,7 +1276,7 @@ impl Resolver { self.add_child(ident, new_parent, ForbidDuplicateValues, ty_m.span); let def = def_static_method(local_def(ty_m.id), - local_def(item.id), + Some(local_def(item.id)), ty_m.purity); (*method_name_bindings).define_value (Public, def, ty_m.span); @@ -1734,27 +1734,105 @@ impl Resolver { current_module = (*child_name_bindings).get_module(); } - // Add the new child item. - let (child_name_bindings, new_parent) = - self.add_child(final_ident, - ModuleReducedGraphParent(current_module), - OverwriteDuplicates, - dummy_sp()); - match path_entry.def_like { dl_def(def) => { + // Add the new child item. + let (child_name_bindings, new_parent) = + self.add_child(final_ident, + ModuleReducedGraphParent( + current_module), + OverwriteDuplicates, + dummy_sp()); + self.handle_external_def(def, modules, child_name_bindings, self.session.str_of(final_ident), final_ident, new_parent); } - dl_impl(_) => { + dl_impl(def) => { // We only process static methods of impls here. debug!("(building reduced graph for external crate) \ processing impl %s", final_ident_str); - // FIXME (#3786): Cross-crate static methods in anonymous - // traits. + match get_type_name_if_impl(self.session.cstore, def) { + None => {} + Some(final_ident) => { + let static_methods_opt = + get_static_methods_if_impl( + self.session.cstore, def); + match static_methods_opt { + Some(static_methods) if + static_methods.len() >= 1 => { + debug!("(building reduced graph for \ + external crate) processing \ + static methods for type name %s", + self.session.str_of(final_ident)); + + let (child_name_bindings, new_parent) = + self.add_child(final_ident, + ModuleReducedGraphParent( + current_module), + OverwriteDuplicates, + dummy_sp()); + + // Process the static methods. First, + // create the module. + let type_module; + match copy child_name_bindings.type_def { + Some(TypeNsDef { + module_def: Some(copy module_def), + _ + }) => { + // We already have a module. This + // is OK. + type_module = module_def; + } + Some(_) | None => { + let parent_link = + self.get_parent_link( + new_parent, final_ident); + child_name_bindings.define_module( + Public, + parent_link, + Some(def), + false, + dummy_sp()); + type_module = + child_name_bindings. + get_module(); + } + } + + // Add each static method to the module. + let new_parent = ModuleReducedGraphParent( + type_module); + for static_methods.each + |static_method_info| { + let ident = static_method_info.ident; + debug!("(building reduced graph for \ + external crate) creating \ + static method '%s'", + self.session.str_of(ident)); + + let (method_name_bindings, _) = + self.add_child( + ident, + new_parent, + OverwriteDuplicates, + dummy_sp()); + let def = def_fn( + static_method_info.def_id, + static_method_info.purity); + method_name_bindings.define_value( + Public, def, dummy_sp()); + } + } + + // Otherwise, do nothing. + Some(_) | None => {} + } + } + } } dl_field => { debug!("(building reduced graph for external crate) \ @@ -1770,7 +1848,6 @@ impl Resolver { module_path: @DVec, subclass: @ImportDirectiveSubclass, span: span) { - let directive = @ImportDirective(privacy, module_path, subclass, span); module_.imports.push(directive); @@ -2453,7 +2530,6 @@ impl Resolver { xray: XrayFlag, span: span) -> ResolveResult<@Module> { - let mut search_module = module_; let mut index = index; let module_path_len = (*module_path).len(); @@ -2648,7 +2724,6 @@ impl Resolver { fn resolve_module_in_lexical_scope(module_: @Module, name: ident) -> ResolveResult<@Module> { - match self.resolve_item_in_lexical_scope(module_, name, TypeNS) { Success(target) => { match target.bindings.type_def { @@ -4035,9 +4110,10 @@ impl Resolver { match self.resolve_path(path, TypeNS, true, visitor) { Some(def) => { debug!("(resolving type) resolved `%s` to \ - type", + type %?", self.session.str_of( - path.idents.last())); + path.idents.last()), + def); result_def = Some(def); } None => { diff --git a/src/rustc/middle/trans/callee.rs b/src/rustc/middle/trans/callee.rs index 133f4647e683..175381a7bd1e 100644 --- a/src/rustc/middle/trans/callee.rs +++ b/src/rustc/middle/trans/callee.rs @@ -75,10 +75,10 @@ fn trans(bcx: block, expr: @ast::expr) -> Callee { fn trans_def(bcx: block, def: ast::def, ref_expr: @ast::expr) -> Callee { match def { - ast::def_fn(did, _) => { + ast::def_fn(did, _) | ast::def_static_method(did, None, _) => { fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id)) } - ast::def_static_method(impl_did, trait_did, _) => { + ast::def_static_method(impl_did, Some(trait_did), _) => { fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did, trait_did, ref_expr.id)) diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 08abe986be6f..30bea1376c00 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -637,11 +637,11 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr, }; match def { - ast::def_fn(did, _) => { + ast::def_fn(did, _) | ast::def_static_method(did, None, _) => { let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id); return fn_data_to_datum(bcx, did, fn_data, lldest); } - ast::def_static_method(impl_did, trait_did, _) => { + ast::def_static_method(impl_did, Some(trait_did), _) => { let fn_data = meth::trans_static_method_callee(bcx, impl_did, trait_did, ref_expr.id); diff --git a/src/test/auxiliary/anon_trait_static_method_lib.rs b/src/test/auxiliary/anon_trait_static_method_lib.rs new file mode 100644 index 000000000000..ec9398dea15e --- /dev/null +++ b/src/test/auxiliary/anon_trait_static_method_lib.rs @@ -0,0 +1,10 @@ +pub struct Foo { + x: int +} + +pub impl Foo { + static fn new() -> Foo { + Foo { x: 3 } + } +} + diff --git a/src/test/run-pass/anon_trait_static_method_exe.rs b/src/test/run-pass/anon_trait_static_method_exe.rs new file mode 100644 index 000000000000..052f95ed3b54 --- /dev/null +++ b/src/test/run-pass/anon_trait_static_method_exe.rs @@ -0,0 +1,13 @@ +// xfail-fast - check-fast doesn't understand aux-build +// aux-build:anon_trait_static_method_lib.rs + +extern mod anon_trait_static_method_lib; +use anon_trait_static_method_lib::Foo; + +fn main() { + let x = Foo::new(); + io::println(x.x.to_str()); +} + + + From acf2d208d617d88b91c3d3282bf3e5e1a9a51c10 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 18 Oct 2012 12:27:09 -0700 Subject: [PATCH 248/292] core: add previous-handler save and restore for proper nesting. --- src/libcore/condition.rs | 94 +++++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 16 deletions(-) diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs index 5f61f2cd53b1..b82f60a9c77e 100644 --- a/src/libcore/condition.rs +++ b/src/libcore/condition.rs @@ -6,9 +6,8 @@ struct Condition { } struct Handler { - // Handler should link to previous handler and - // reinstall it when popped. - handle: RustClosure + handle: RustClosure, + prev: Option<@Handler> } @@ -21,7 +20,17 @@ struct PopHandler { cond: &Condition, drop { unsafe { - task::local_data::local_data_pop(self.cond.key); + debug!("PopHandler: popping handler from TLS"); + match task::local_data::local_data_pop(self.cond.key) { + None => (), + Some(h) => { + match h.prev { + None => (), + Some(p) => + task::local_data::local_data_set(self.cond.key, p) + } + } + } } } } @@ -31,13 +40,16 @@ struct HandleBlock { handler: @Handler, drop { unsafe { + debug!("HandleBlock: pushing handler to TLS"); task::local_data::local_data_set(self.pb.cond.key, self.handler); let _pop = PopHandler { cond: self.pb.cond }; // transmutation to avoid copying non-copyable, should // be fixable by tracking closure pointees in regionck. let f : &fn() = ::cast::transmute(self.pb.inner); + debug!("HandleBlock: invoking protected code"); f(); + debug!("HandleBlock: returned from protected code"); } } } @@ -45,9 +57,11 @@ struct HandleBlock { impl ProtectBlock { fn handle(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self { unsafe { + debug!("ProtectBlock.handle: setting up handler block"); let p : *RustClosure = ::cast::transmute(&h); + let prev = task::local_data::local_data_get(self.cond.key); HandleBlock { pb: self, - handler: @Handler{handle: *p} } + handler: @Handler{handle: *p, prev: prev} } } } } @@ -59,17 +73,23 @@ impl Condition { unsafe { // transmutation to avoid copying non-copyable, should // be fixable by tracking closure pointees in regionck. + debug!("Condition.protect: setting up protected block"); let p : *RustClosure = ::cast::transmute(&inner); ProtectBlock { cond: self, - inner: *p } } + inner: *p } + } } fn raise(t:&T) -> U { unsafe { match task::local_data::local_data_get(self.key) { - None => fail, + None => { + debug!("Condition.raise: found no handler"); + fail + } + Some(handler) => { - io::println("got handler"); + debug!("Condition.raise: found handler"); let f : &fn(&T) -> U = ::cast::transmute(handler.handle); f(t) } @@ -79,39 +99,81 @@ impl Condition { } -#[test] +#[cfg(test)] fn happiness_key(_x: @Handler) { } -#[test] +#[cfg(test)] fn sadness_key(_x: @Handler) { } -#[test] +#[cfg(test)] fn trouble(i: int) { // Condition should work as a const, just limitations in consts. let sadness_condition : Condition = Condition { key: sadness_key }; - io::println("raising"); + debug!("trouble: raising conition"); let j = sadness_condition.raise(&i); - io::println(fmt!("handler recovered with %d", j)); + debug!("trouble: handler recovered with %d", j); } #[test] -fn test() { +fn test1() { let sadness_condition : Condition = Condition { key: sadness_key }; let mut i = 10; let b = do sadness_condition.protect { - io::println("in protected block"); + debug!("test1: in protected block"); trouble(1); trouble(2); trouble(3); }; do b.handle |j| { + debug!("test1: in handler"); i += *j; i }; assert i == 16; -} \ No newline at end of file +} +#[cfg(test)] +fn nested_test_inner() { + let sadness_condition : Condition = Condition { key: sadness_key }; + + let mut inner_trapped = false; + + let b = do sadness_condition.protect { + debug!("nested_test_inner: in protected block"); + trouble(1); + }; + + do b.handle |_j:&int| { + debug!("nested_test_inner: in handler"); + inner_trapped = true; + 0 + }; + + assert inner_trapped; +} + +#[test] +fn nested_test_outer() { + + let sadness_condition : Condition = Condition { key: sadness_key }; + + let mut outer_trapped = false; + + let b = do sadness_condition.protect { + debug!("nested_test_outer: in protected block"); + nested_test_inner(); + trouble(1); + }; + + do b.handle |_j:&int| { + debug!("nested_test_outer: in handler"); + outer_trapped = true; + 0 + }; + + assert outer_trapped; +} From 33795bc4d39227818f1ea849bee50216235e8a0f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 18 Oct 2012 13:04:52 -0700 Subject: [PATCH 249/292] configure: fix use of bash-specific here strings (also awk, please no more deps). --- configure | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/configure b/configure index cd500b6ec43a..3ff72afe67f8 100755 --- a/configure +++ b/configure @@ -362,11 +362,15 @@ fi if [ ! -z "$CFG_PANDOC" ] then - read PV_MAJOR PV_MINOR <<<$(pandoc --version | awk '/^pandoc/ {split($2, PV, "."); print PV[1] " " PV[2]}') + PANDOC_VER_LINE=$(pandoc --version | grep '^pandoc ') + PANDOC_VER=${PANDOC_VER_LINE#pandoc } + PV_MAJOR_MINOR=${PANDOC_VER%.[0-9]} + PV_MAJOR=${PV_MAJOR_MINOR%.[0-9]} + PV_MINOR=${PV_MAJOR_MINOR#[0-9].} if [ "$PV_MAJOR" -lt "1" ] || [ "$PV_MINOR" -lt "8" ] then - step_msg "pandoc $PV_MAJOR.$PV_MINOR is too old. disabling" - BAD_PANDOC=1 + step_msg "pandoc $PV_MAJOR.$PV_MINOR is too old. disabling" + BAD_PANDOC=1 fi fi From e0b71dd6b3bac9596356377ec81608358fd1ca08 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 18 Oct 2012 13:05:02 -0700 Subject: [PATCH 250/292] configure: note dep on head. --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 3ff72afe67f8..c275b1a096a1 100755 --- a/configure +++ b/configure @@ -187,6 +187,7 @@ need_cmd cmp need_cmd mkdir need_cmd printf need_cmd cut +need_cmd head need_cmd grep need_cmd xargs need_cmd cp From 3d76a751934786383786b3ba3daf7e9f4bf08822 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Thu, 18 Oct 2012 20:58:57 -0400 Subject: [PATCH 251/292] configure: check for pandoc version properly. --- configure | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/configure b/configure index c275b1a096a1..da1be03dfba9 100755 --- a/configure +++ b/configure @@ -363,11 +363,12 @@ fi if [ ! -z "$CFG_PANDOC" ] then - PANDOC_VER_LINE=$(pandoc --version | grep '^pandoc ') - PANDOC_VER=${PANDOC_VER_LINE#pandoc } - PV_MAJOR_MINOR=${PANDOC_VER%.[0-9]} - PV_MAJOR=${PV_MAJOR_MINOR%.[0-9]} - PV_MINOR=${PV_MAJOR_MINOR#[0-9].} + PANDOC_VER_LINE=$(pandoc --version | grep '^pandoc ') + PANDOC_VER=${PANDOC_VER_LINE#pandoc } + PV_MAJOR_MINOR=${PANDOC_VER%.[0-9]*} + PV_MAJOR=${PV_MAJOR_MINOR%%[.][0-9]*} + PV_MINOR=${PV_MAJOR_MINOR#[0-9]*[.]} + PV_MINOR=${PV_MINOR%%[.][0-9]*} if [ "$PV_MAJOR" -lt "1" ] || [ "$PV_MINOR" -lt "8" ] then step_msg "pandoc $PV_MAJOR.$PV_MINOR is too old. disabling" From 34aabe5051c1d9666ac673d9da2e8413a694a169 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 18 Oct 2012 19:17:04 -0700 Subject: [PATCH 252/292] Add Luqman Aden to AUTHORS --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 08a3ec77807c..14b20aa3c484 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -72,6 +72,7 @@ Kevin Cantu Lennart Kudling Lindsey Kuper Luca Bruno +Luqman Aden Magnus Auvinen Margaret Meyerhofer Marijn Haverbeke From 6c4ad31f764aa8ebec3873ce68770b4173b0b97d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 18 Oct 2012 18:45:33 -0700 Subject: [PATCH 253/292] core: Add type params to condition handling so interface is safe. --- src/libcore/condition.rs | 49 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs index b82f60a9c77e..d50c01683d80 100644 --- a/src/libcore/condition.rs +++ b/src/libcore/condition.rs @@ -1,23 +1,23 @@ // helper for transmutation, shown below. type RustClosure = (int,int); -struct Condition { - key: task::local_data::LocalDataKey +struct Condition { + key: task::local_data::LocalDataKey> } -struct Handler { +struct Handler { handle: RustClosure, - prev: Option<@Handler> + prev: Option<@Handler> } -struct ProtectBlock { - cond: &Condition, +struct ProtectBlock { + cond: &Condition, inner: RustClosure } -struct PopHandler { - cond: &Condition, +struct PopHandler { + cond: &Condition, drop { unsafe { debug!("PopHandler: popping handler from TLS"); @@ -35,9 +35,9 @@ struct PopHandler { } } -struct HandleBlock { - pb: &ProtectBlock, - handler: @Handler, +struct HandleBlock { + pb: &ProtectBlock, + handler: @Handler, drop { unsafe { debug!("HandleBlock: pushing handler to TLS"); @@ -54,8 +54,8 @@ struct HandleBlock { } } -impl ProtectBlock { - fn handle(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self { +impl ProtectBlock { + fn handle(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self { unsafe { debug!("ProtectBlock.handle: setting up handler block"); let p : *RustClosure = ::cast::transmute(&h); @@ -67,9 +67,9 @@ impl ProtectBlock { } -impl Condition { +impl Condition { - fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self { + fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self { unsafe { // transmutation to avoid copying non-copyable, should // be fixable by tracking closure pointees in regionck. @@ -80,7 +80,7 @@ impl Condition { } } - fn raise(t:&T) -> U { + fn raise(t:&T) -> U { unsafe { match task::local_data::local_data_get(self.key) { None => { @@ -100,15 +100,13 @@ impl Condition { #[cfg(test)] -fn happiness_key(_x: @Handler) { } - -#[cfg(test)] -fn sadness_key(_x: @Handler) { } +fn sadness_key(_x: @Handler) { } #[cfg(test)] fn trouble(i: int) { // Condition should work as a const, just limitations in consts. - let sadness_condition : Condition = Condition { key: sadness_key }; + let sadness_condition : Condition = + Condition { key: sadness_key }; debug!("trouble: raising conition"); let j = sadness_condition.raise(&i); debug!("trouble: handler recovered with %d", j); @@ -117,7 +115,8 @@ fn trouble(i: int) { #[test] fn test1() { - let sadness_condition : Condition = Condition { key: sadness_key }; + let sadness_condition : Condition = + Condition { key: sadness_key }; let mut i = 10; @@ -138,7 +137,8 @@ fn test1() { } #[cfg(test)] fn nested_test_inner() { - let sadness_condition : Condition = Condition { key: sadness_key }; + let sadness_condition : Condition = + Condition { key: sadness_key }; let mut inner_trapped = false; @@ -159,7 +159,8 @@ fn nested_test_inner() { #[test] fn nested_test_outer() { - let sadness_condition : Condition = Condition { key: sadness_key }; + let sadness_condition : Condition = + Condition { key: sadness_key }; let mut outer_trapped = false; From c97944fbf810720c2bcb0ccbe1c3149a3d9be4c0 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 18 Oct 2012 19:47:19 -0700 Subject: [PATCH 254/292] core: add potential "simpler interface" to core::condition, also reduce TLS hits. --- src/libcore/condition.rs | 87 +++++++++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs index d50c01683d80..a50c29b0f924 100644 --- a/src/libcore/condition.rs +++ b/src/libcore/condition.rs @@ -6,8 +6,7 @@ struct Condition { } struct Handler { - handle: RustClosure, - prev: Option<@Handler> + handle: RustClosure } @@ -16,20 +15,16 @@ struct ProtectBlock { inner: RustClosure } -struct PopHandler { +struct Guard { cond: &Condition, + prev: Option<@Handler>, drop { - unsafe { - debug!("PopHandler: popping handler from TLS"); - match task::local_data::local_data_pop(self.cond.key) { - None => (), - Some(h) => { - match h.prev { - None => (), - Some(p) => - task::local_data::local_data_set(self.cond.key, p) - } - } + match self.prev { + None => (), + Some(p) => + unsafe { + debug!("Guard: popping handler from TLS"); + task::local_data::local_data_set(self.cond.key, p) } } } @@ -37,13 +32,15 @@ struct PopHandler { struct HandleBlock { pb: &ProtectBlock, + prev: Option<@Handler>, handler: @Handler, drop { unsafe { debug!("HandleBlock: pushing handler to TLS"); + let _g = Guard { cond: self.pb.cond, + prev: self.prev }; task::local_data::local_data_set(self.pb.cond.key, self.handler); - let _pop = PopHandler { cond: self.pb.cond }; // transmutation to avoid copying non-copyable, should // be fixable by tracking closure pointees in regionck. let f : &fn() = ::cast::transmute(self.pb.inner); @@ -61,7 +58,8 @@ impl ProtectBlock { let p : *RustClosure = ::cast::transmute(&h); let prev = task::local_data::local_data_get(self.cond.key); HandleBlock { pb: self, - handler: @Handler{handle: *p, prev: prev} } + prev: prev, + handler: @Handler{handle: *p} } } } } @@ -69,6 +67,18 @@ impl ProtectBlock { impl Condition { + fn guard(&self, h: &self/fn(&T) ->U) -> Guard/&self { + unsafe { + let prev = task::local_data::local_data_get(self.key); + let g = Guard { cond: self, prev: prev }; + debug!("Guard: pushing handler to TLS"); + let p : *RustClosure = ::cast::transmute(&h); + let h = @Handler{handle: *p}; + task::local_data::local_data_set(self.key, h); + move g + } + } + fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self { unsafe { // transmutation to avoid copying non-copyable, should @@ -147,7 +157,7 @@ fn nested_test_inner() { trouble(1); }; - do b.handle |_j:&int| { + do b.handle |_j| { debug!("nested_test_inner: in handler"); inner_trapped = true; 0 @@ -170,7 +180,7 @@ fn nested_test_outer() { trouble(1); }; - do b.handle |_j:&int| { + do b.handle |_j| { debug!("nested_test_outer: in handler"); outer_trapped = true; 0 @@ -178,3 +188,44 @@ fn nested_test_outer() { assert outer_trapped; } + + +#[cfg(test)] +fn nested_guard_test_inner() { + let sadness_condition : Condition = + Condition { key: sadness_key }; + + let mut inner_trapped = false; + + let _g = do sadness_condition.guard |_j| { + debug!("nested_guard_test_inner: in handler"); + inner_trapped = true; + 0 + }; + + debug!("nested_guard_test_inner: in protected block"); + trouble(1); + + assert inner_trapped; +} + +#[test] +fn nested_guard_test_outer() { + + let sadness_condition : Condition = + Condition { key: sadness_key }; + + let mut outer_trapped = false; + + let _g = do sadness_condition.guard |_j| { + debug!("nested_guard_test_outer: in handler"); + outer_trapped = true; + 0 + }; + + debug!("nested_guard_test_outer: in protected block"); + nested_guard_test_inner(); + trouble(1); + + assert outer_trapped; +} From 10612ee30c31d33885f233c3e5839574fdb8be80 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 19 Oct 2012 11:37:00 -0700 Subject: [PATCH 255/292] Remove superfluous by-ref in option::get, option::get_default, option::expect Superficial change, no review. --- src/fuzzer/fuzzer.rs | 2 +- src/libcore/dlist.rs | 24 ++++++++++++------------ src/libcore/iter-trait/dlist.rs | 2 +- src/libcore/option.rs | 18 +++++++++--------- src/libcore/os.rs | 2 +- src/libstd/map.rs | 2 +- src/rustc/middle/trans/alt.rs | 2 +- src/rustc/middle/trans/meth.rs | 2 +- src/rustc/middle/trans/monomorphize.rs | 4 ++-- src/rustc/middle/trans/reflect.rs | 2 +- src/rustdoc/attr_pass.rs | 4 ++-- src/rustdoc/doc.rs | 2 +- src/test/run-pass/test-ignore-cfg.rs | 4 ++-- 13 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/fuzzer/fuzzer.rs b/src/fuzzer/fuzzer.rs index 018972d4c3e0..a4968382cf47 100644 --- a/src/fuzzer/fuzzer.rs +++ b/src/fuzzer/fuzzer.rs @@ -296,7 +296,7 @@ fn check_variants_T( } fn last_part(filename: ~str) -> ~str { - let ix = option::get(&str::rfind_char(filename, '/')); + let ix = option::get(str::rfind_char(filename, '/')); str::slice(filename, ix + 1u, str::len(filename) - 3u) } diff --git a/src/libcore/dlist.rs b/src/libcore/dlist.rs index 3bcf486ef7e0..35399878e261 100644 --- a/src/libcore/dlist.rs +++ b/src/libcore/dlist.rs @@ -208,7 +208,7 @@ impl DList { fn push_head_n(data: T) -> DListNode { let mut nobe = self.new_link(move data); self.add_head(nobe); - option::get(&nobe) + option::get(nobe) } /// Add data to the tail of the list. O(1). fn push(data: T) { @@ -221,7 +221,7 @@ impl DList { fn push_n(data: T) -> DListNode { let mut nobe = self.new_link(move data); self.add_tail(nobe); - option::get(&nobe) + option::get(nobe) } /** * Insert data into the middle of the list, left of the given node. @@ -245,7 +245,7 @@ impl DList { fn insert_before_n(data: T, neighbour: DListNode) -> DListNode { let mut nobe = self.new_link(move data); self.insert_left(nobe, neighbour); - option::get(&nobe) + option::get(nobe) } /** * Insert data into the middle of the list, right of the given node. @@ -269,7 +269,7 @@ impl DList { fn insert_after_n(data: T, neighbour: DListNode) -> DListNode { let mut nobe = self.new_link(move data); self.insert_right(neighbour, nobe); - option::get(&nobe) + option::get(nobe) } /// Remove a node from the head of the list. O(1). @@ -385,17 +385,17 @@ impl DList { let mut link = self.peek_n(); let mut rabbit = link; while option::is_some(&link) { - let nobe = option::get(&link); + let nobe = option::get(link); assert nobe.linked; // check cycle if option::is_some(&rabbit) { - rabbit = option::get(&rabbit).next; + rabbit = option::get(rabbit).next; } if option::is_some(&rabbit) { - rabbit = option::get(&rabbit).next; + rabbit = option::get(rabbit).next; } if option::is_some(&rabbit) { - assert !box::ptr_eq(*option::get(&rabbit), *nobe); + assert !box::ptr_eq(*option::get(rabbit), *nobe); } // advance link = nobe.next_link(); @@ -406,17 +406,17 @@ impl DList { link = self.peek_tail_n(); rabbit = link; while option::is_some(&link) { - let nobe = option::get(&link); + let nobe = option::get(link); assert nobe.linked; // check cycle if option::is_some(&rabbit) { - rabbit = option::get(&rabbit).prev; + rabbit = option::get(rabbit).prev; } if option::is_some(&rabbit) { - rabbit = option::get(&rabbit).prev; + rabbit = option::get(rabbit).prev; } if option::is_some(&rabbit) { - assert !box::ptr_eq(*option::get(&rabbit), *nobe); + assert !box::ptr_eq(*option::get(rabbit), *nobe); } // advance link = nobe.prev_link(); diff --git a/src/libcore/iter-trait/dlist.rs b/src/libcore/iter-trait/dlist.rs index 2a5bb59b0c1f..1b5f11569c37 100644 --- a/src/libcore/iter-trait/dlist.rs +++ b/src/libcore/iter-trait/dlist.rs @@ -11,7 +11,7 @@ pub type IMPL_T = dlist::DList; pub pure fn EACH(self: &IMPL_T, f: fn(v: &A) -> bool) { let mut link = self.peek_n(); while option::is_some(&link) { - let nobe = option::get(&link); + let nobe = option::get(link); assert nobe.linked; if !f(&nobe.data) { break; } // Check (weakly) that the user didn't do a remove. diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 50489a820291..baabc35b428c 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -42,7 +42,7 @@ pub enum Option { Some(T), } -pub pure fn get(opt: &Option) -> T { +pub pure fn get(opt: Option) -> T { /*! Gets the value out of an option @@ -58,7 +58,7 @@ pub pure fn get(opt: &Option) -> T { case explicitly. */ - match *opt { + match opt { Some(copy x) => return x, None => fail ~"option::get none" } @@ -85,7 +85,7 @@ pub pure fn get_ref(opt: &r/Option) -> &r/T { } } -pub pure fn expect(opt: &Option, reason: ~str) -> T { +pub pure fn expect(opt: Option, reason: ~str) -> T { /*! * Gets the value out of an option, printing a specified message on * failure @@ -94,7 +94,7 @@ pub pure fn expect(opt: &Option, reason: ~str) -> T { * * Fails if the value equals `none` */ - match *opt { Some(copy x) => x, None => fail reason } + match opt { Some(copy x) => x, None => fail reason } } pub pure fn map(opt: &Option, f: fn(x: &T) -> U) -> Option { @@ -167,10 +167,10 @@ pub pure fn is_some(opt: &Option) -> bool { !is_none(opt) } -pub pure fn get_default(opt: &Option, def: T) -> T { +pub pure fn get_default(opt: Option, def: T) -> T { //! Returns the contained value or a default - match *opt { Some(copy x) => x, None => def } + match opt { Some(copy x) => x, None => def } } pub pure fn map_default(opt: &Option, def: U, @@ -284,8 +284,8 @@ impl Option { Instead, prefer to use pattern matching and handle the `None` case explicitly. */ - pure fn get() -> T { get(&self) } - pure fn get_default(def: T) -> T { get_default(&self, def) } + pure fn get() -> T { get(self) } + pure fn get_default(def: T) -> T { get_default(self, def) } /** * Gets the value out of an option, printing a specified message on * failure @@ -294,7 +294,7 @@ impl Option { * * Fails if the value equals `none` */ - pure fn expect(reason: ~str) -> T { expect(&self, move reason) } + pure fn expect(reason: ~str) -> T { expect(self, move reason) } /// Applies a function zero or more times until the result is none. pure fn while_some(blk: fn(v: T) -> Option) { while_some(self, blk) } } diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 24e4d7eff41f..d201761d86be 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -473,7 +473,7 @@ pub fn tmpdir() -> Path { #[cfg(unix)] #[allow(non_implicitly_copyable_typarams)] fn lookup() -> Path { - option::get_default(&getenv_nonempty("TMPDIR"), + option::get_default(getenv_nonempty("TMPDIR"), Path("/tmp")) } diff --git a/src/libstd/map.rs b/src/libstd/map.rs index 9f78f98fa316..e49f1abd02b4 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -723,7 +723,7 @@ mod tests { let map = map::HashMap::<~str, ~str>(); assert (option::is_none(&map.find(key))); map.insert(key, ~"val"); - assert (option::get(&map.find(key)) == ~"val"); + assert (option::get(map.find(key)) == ~"val"); } #[test] diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index d760bc349073..6de9ad977c9f 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -353,7 +353,7 @@ fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint, match p.node { ast::pat_enum(_, subpats) => { if opt_eq(tcx, &variant_opt(tcx, p.id), opt) { - Some(option::get_default(&subpats, + Some(option::get_default(subpats, vec::from_elem(variant_size, dummy))) } else { diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs index 89b101ab8759..fadde08b9f89 100644 --- a/src/rustc/middle/trans/meth.rs +++ b/src/rustc/middle/trans/meth.rs @@ -299,7 +299,7 @@ fn trans_static_method_callee(bcx: block, fn method_from_methods(ms: ~[@ast::method], name: ast::ident) -> ast::def_id { - local_def(option::get(&vec::find(ms, |m| m.ident == name)).id) + local_def(option::get(vec::find(ms, |m| m.ident == name)).id) } fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id, diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index f6763206e18c..aadd6fc7957a 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -113,7 +113,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, ccx.stats.n_monos += 1; - let depth = option::get_default(&ccx.monomorphizing.find(fn_id), 0u); + let depth = option::get_default(ccx.monomorphizing.find(fn_id), 0u); // Random cut-off -- code that needs to instantiate the same function // recursively more than ten times can probably safely be assumed to be // causing an infinite expansion. @@ -158,7 +158,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, } ast_map::node_variant(v, enum_item, _) => { let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id)); - let this_tv = option::get(&vec::find(*tvs, |tv| { + let this_tv = option::get(vec::find(*tvs, |tv| { tv.id.node == fn_id.node})); let d = mk_lldecl(); set_inline_hint(d); diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index 18a25888bb46..c52b653d536c 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -57,7 +57,7 @@ impl reflector { fn visit(ty_name: ~str, args: ~[ValueRef]) { let tcx = self.bcx.tcx(); - let mth_idx = option::get(&ty::method_idx( + let mth_idx = option::get(ty::method_idx( tcx.sess.ident_of(~"visit_" + ty_name), *self.visitor_methods)); let mth_ty = ty::mk_fn(tcx, self.visitor_methods[mth_idx].fty); diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs index cd310791b4df..0748f603580b 100644 --- a/src/rustdoc/attr_pass.rs +++ b/src/rustdoc/attr_pass.rs @@ -52,7 +52,7 @@ fn fold_crate( { topmod: doc::ModDoc_({ item: { - name: option::get_default(&attrs.name, doc.topmod.name()), + name: option::get_default(attrs.name, doc.topmod.name()), .. doc.topmod.item }, .. *doc.topmod @@ -151,7 +151,7 @@ fn fold_enum( node: ast::item_enum(enum_definition, _), _ }, _) => { let ast_variant = option::get( - &vec::find(enum_definition.variants, |v| { + vec::find(enum_definition.variants, |v| { to_str(v.node.name) == variant.name })); diff --git a/src/rustdoc/doc.rs b/src/rustdoc/doc.rs index 0764d9e24326..2d5bf5fc3c69 100644 --- a/src/rustdoc/doc.rs +++ b/src/rustdoc/doc.rs @@ -377,7 +377,7 @@ impl IndexEntry : cmp::Eq { impl Doc { fn CrateDoc() -> CrateDoc { - option::get(&vec::foldl(None, self.pages, |_m, page| { + option::get(vec::foldl(None, self.pages, |_m, page| { match *page { doc::CratePage(doc) => Some(doc), _ => None diff --git a/src/test/run-pass/test-ignore-cfg.rs b/src/test/run-pass/test-ignore-cfg.rs index 0482fc278c81..0baabecb0ab9 100644 --- a/src/test/run-pass/test-ignore-cfg.rs +++ b/src/test/run-pass/test-ignore-cfg.rs @@ -20,10 +20,10 @@ fn checktests() { let tests = __test::tests(); let shouldignore = option::get( - &vec::find(tests, |t| t.name == ~"shouldignore" )); + vec::find(tests, |t| t.name == ~"shouldignore" )); assert shouldignore.ignore == true; let shouldnotignore = option::get( - &vec::find(tests, |t| t.name == ~"shouldnotignore" )); + vec::find(tests, |t| t.name == ~"shouldnotignore" )); assert shouldnotignore.ignore == false; } \ No newline at end of file From 8492a029e8741d80489a6c8d0e673927ead95b7c Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 19 Oct 2012 11:44:01 -0700 Subject: [PATCH 256/292] Fix Windows breakage --- src/libcore/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/os.rs b/src/libcore/os.rs index d201761d86be..a834bb84f8d8 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -481,7 +481,7 @@ pub fn tmpdir() -> Path { #[allow(non_implicitly_copyable_typarams)] fn lookup() -> Path { option::get_default( - &option::or(getenv_nonempty("TMP"), + option::or(getenv_nonempty("TMP"), option::or(getenv_nonempty("TEMP"), option::or(getenv_nonempty("USERPROFILE"), getenv_nonempty("WINDIR")))), From 81e66ae1fbc8e76a21c78d6c0aeab9119263dfee Mon Sep 17 00:00:00 2001 From: Mahmut Bulut Date: Mon, 15 Oct 2012 23:53:16 +0300 Subject: [PATCH 257/292] Renaming trait name UniqueStr to Trimmable --- src/libcore/core.rs | 2 +- src/libcore/str.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/core.rs b/src/libcore/core.rs index 5ef11a4ad464..35131e561d95 100644 --- a/src/libcore/core.rs +++ b/src/libcore/core.rs @@ -12,7 +12,7 @@ pub use WindowsPath = path::WindowsPath; pub use PosixPath = path::PosixPath; pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; -pub use str::{StrSlice, UniqueStr}; +pub use str::{StrSlice, Trimmable}; pub use vec::{ConstVector, CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; pub use vec::{MutableVector, MutableCopyableVector}; diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 3da41ac6abc8..0c722c437ee5 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2075,14 +2075,14 @@ pub mod raw { } -pub trait UniqueStr { +pub trait Trimmable { pure fn trim() -> self; pure fn trim_left() -> self; pure fn trim_right() -> self; } /// Extension methods for strings -impl ~str: UniqueStr { +impl ~str: Trimmable { /// Returns a string with leading and trailing whitespace removed #[inline] pure fn trim() -> ~str { trim(self) } From 0243d86e19295d9e25e6fa83005f0aa03eef519e Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 19 Oct 2012 12:31:54 -0700 Subject: [PATCH 258/292] Add Mahmut Bulut to AUTHORS --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 14b20aa3c484..90690a0a3eaf 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -74,6 +74,7 @@ Lindsey Kuper Luca Bruno Luqman Aden Magnus Auvinen +Mahmut Bulut Margaret Meyerhofer Marijn Haverbeke Matt Brubeck From 89de49cecdf5e48497e5770eba13240091627320 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 19 Oct 2012 14:46:32 -0700 Subject: [PATCH 259/292] core: add 3rd proposed interface (trap/in) to conditions. --- src/libcore/condition.rs | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs index a50c29b0f924..77bd88e04d78 100644 --- a/src/libcore/condition.rs +++ b/src/libcore/condition.rs @@ -51,6 +51,11 @@ struct HandleBlock { } } +struct Trap { + cond: &Condition, + handler: @Handler +} + impl ProtectBlock { fn handle(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self { unsafe { @@ -65,6 +70,20 @@ impl ProtectBlock { } + +impl Trap { + fn in(&self, inner: &self/fn() -> V) -> V { + unsafe { + let prev = task::local_data::local_data_get(self.cond.key); + let _g = Guard { cond: self.cond, + prev: prev }; + debug!("Trap: pushing handler to TLS"); + task::local_data::local_data_set(self.cond.key, self.handler); + inner() + } + } +} + impl Condition { fn guard(&self, h: &self/fn(&T) ->U) -> Guard/&self { @@ -79,6 +98,14 @@ impl Condition { } } + fn trap(&self, h: &self/fn(&T) ->U) -> Trap/&self { + unsafe { + let p : *RustClosure = ::cast::transmute(&h); + let h = @Handler{handle: *p}; + move Trap { cond: self, handler: h } + } + } + fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self { unsafe { // transmutation to avoid copying non-copyable, should @@ -229,3 +256,45 @@ fn nested_guard_test_outer() { assert outer_trapped; } + + + +#[cfg(test)] +fn nested_trap_test_inner() { + let sadness_condition : Condition = + Condition { key: sadness_key }; + + let mut inner_trapped = false; + + do sadness_condition.trap(|_j| { + debug!("nested_trap_test_inner: in handler"); + inner_trapped = true; + 0 + }).in { + debug!("nested_trap_test_inner: in protected block"); + trouble(1); + } + + assert inner_trapped; +} + +#[test] +fn nested_trap_test_outer() { + + let sadness_condition : Condition = + Condition { key: sadness_key }; + + let mut outer_trapped = false; + + do sadness_condition.trap(|_j| { + debug!("nested_trap_test_outer: in handler"); + outer_trapped = true; 0 + }).in { + debug!("nested_guard_test_outer: in protected block"); + nested_trap_test_inner(); + trouble(1); + } + + + assert outer_trapped; +} From c05d96c191085689459aebed719fa5f3ab1fa955 Mon Sep 17 00:00:00 2001 From: Mahmut Bulut Date: Mon, 15 Oct 2012 23:30:06 +0300 Subject: [PATCH 260/292] Valgrind check disable --- Makefile.in | 2 +- configure | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index 383793be6f89..d6ede37c4aa7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -368,7 +368,7 @@ endif STAGE$(1)_T_$(2)_H_$(3) := \ $$(Q)$$(call CFG_RUN_TARG,$(1), \ - $$(CFG_VALGRIND_COMPILE$(1)) \ +## $$(CFG_VALGRIND_COMPILE$(1)) \ $$(HBIN$(1)_H_$(3))/rustc$$(X) \ --cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3)) \ $$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) diff --git a/configure b/configure index da1be03dfba9..9da652762a74 100755 --- a/configure +++ b/configure @@ -294,7 +294,7 @@ else fi opt sharedstd 1 "build libstd as a shared library" -opt valgrind 1 "run tests with valgrind (memcheck by default)" +opt valgrind 0 "run tests with valgrind (memcheck by default)" opt helgrind 0 "run tests with helgrind instead of memcheck" opt docs 1 "build documentation" opt optimize 1 "build optimized rust code" From 55d134d29adc0e6cd0a6dab188c9c7c693d0948b Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 14:27:56 -0700 Subject: [PATCH 261/292] Some tweaks to the valgrind makefile code This reenables valgrinding of the compiler and prints a message when the user _is_ valgrinding --- Makefile.in | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile.in b/Makefile.in index d6ede37c4aa7..fb674878f556 100644 --- a/Makefile.in +++ b/Makefile.in @@ -144,8 +144,9 @@ ifneq ($(wildcard $(CFG_GIT_DIR)),) endif endif -ifdef CFG_DISABLE_VALGRIND - $(info cfg: disabling valgrind (CFG_DISABLE_VALGRIND)) +ifdef CFG_ENABLE_VALGRIND + $(info cfg: enabling valgrind (CFG_ENABLE_VALGRIND)) +else CFG_VALGRIND := endif ifdef CFG_BAD_VALGRIND @@ -368,7 +369,7 @@ endif STAGE$(1)_T_$(2)_H_$(3) := \ $$(Q)$$(call CFG_RUN_TARG,$(1), \ -## $$(CFG_VALGRIND_COMPILE$(1)) \ + $$(CFG_VALGRIND_COMPILE$(1)) \ $$(HBIN$(1)_H_$(3))/rustc$$(X) \ --cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3)) \ $$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) From 15777de957642ebace789bec747b4269ca9883b7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 14:52:31 -0700 Subject: [PATCH 262/292] Fix run-pass/issue-2895 for 32-bit archs --- src/test/run-pass/issue-2895.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/run-pass/issue-2895.rs b/src/test/run-pass/issue-2895.rs index b51e6360e524..1765e8638a63 100644 --- a/src/test/run-pass/issue-2895.rs +++ b/src/test/run-pass/issue-2895.rs @@ -10,7 +10,14 @@ struct Kitty { drop {} } +#[cfg(target_arch = "x86_64")] fn main() { assert (size_of::() == 8 as uint); assert (size_of::() == 16 as uint); } + +#[cfg(target_arch = "x86")] +fn main() { + assert (size_of::() == 4 as uint); + assert (size_of::() == 8 as uint); +} From 0e2437bf5d4a1f863888d4b0b5995a695f966e73 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Fri, 19 Oct 2012 19:28:58 -0400 Subject: [PATCH 263/292] uv: implement a way to get client's ip/port. --- src/libstd/net_ip.rs | 23 +++++++++++++++++++++-- src/libstd/net_tcp.rs | 16 ++++++++++++++++ src/libstd/uv_ll.rs | 22 ++++++++++++++++++++++ src/rt/rust_uv.cpp | 22 ++++++++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index cf5323c498b7..5d78fb19bab3 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -10,8 +10,10 @@ use addrinfo = uv::ll::addrinfo; use uv_getaddrinfo_t = uv::ll::uv_getaddrinfo_t; use uv_ip4_addr = uv::ll::ip4_addr; use uv_ip4_name = uv::ll::ip4_name; +use uv_ip4_port = uv::ll::ip4_port; use uv_ip6_addr = uv::ll::ip6_addr; use uv_ip6_name = uv::ll::ip6_name; +use uv_ip6_port = uv::ll::ip6_port; use uv_getaddrinfo = uv::ll::getaddrinfo; use uv_freeaddrinfo = uv::ll::freeaddrinfo; use create_uv_getaddrinfo_t = uv::ll::getaddrinfo_t; @@ -33,11 +35,11 @@ type ParseAddrErr = { }; /** - * Convert a `ip_addr` to a str + * Convert a `IpAddr` to a str * * # Arguments * - * * ip - a `std::net::ip::ip_addr` + * * ip - a `std::net::ip::IpAddr` */ pub fn format_addr(ip: &IpAddr) -> ~str { match *ip { @@ -58,6 +60,23 @@ pub fn format_addr(ip: &IpAddr) -> ~str { } } +/** + * Get the associated port + * + * # Arguments + * * ip - a `std::net::ip::IpAddr` + */ +pub fn get_port(ip: &IpAddr) -> uint { + match *ip { + Ipv4(ref addr) => unsafe { + uv_ip4_port(addr) + }, + Ipv6(ref addr) => unsafe { + uv_ip6_port(addr) + } + } +} + /// Represents errors returned from `net::ip::get_addr()` enum IpGetAddrErr { GetAddrUnknownError diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index db5c1328e62b..94293c3aa41b 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -746,6 +746,22 @@ impl TcpSocket { -> future::Future> { write_future(&self, raw_write_data) } + pub fn getpeername() -> ip::IpAddr { + unsafe { + let addr = uv::ll::ip4_addr("", 0); + uv::ll::tcp_getpeername(self.socket_data.stream_handle_ptr, + ptr::addr_of(&addr)); + ip::Ipv4(move addr) + } + } + pub fn getpeername6() -> ip::IpAddr { + unsafe { + let addr = uv::ll::ip6_addr("", 0); + uv::ll::tcp_getpeername6(self.socket_data.stream_handle_ptr, + ptr::addr_of(&addr)); + ip::Ipv6(move addr) + } + } } /// Implementation of `io::reader` trait for a buffered `net::tcp::tcp_socket` diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index b4b04a1a714f..c12682fcc928 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -590,6 +590,8 @@ extern mod rustrt { -> libc::c_int; fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: libc::size_t) -> libc::c_int; + fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint; + fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint; // FIXME ref #2064 fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, @@ -606,6 +608,10 @@ extern mod rustrt { // FIXME ref #2064 fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, ++addr: *sockaddr_in6) -> libc::c_int; + fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, + ++name: *sockaddr_in) -> libc::c_int; + fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, + ++name: *sockaddr_in6) ->libc::c_int; fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int, cb: *u8) -> libc::c_int; fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void) @@ -736,6 +742,16 @@ pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, addr_ptr); } +pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, + name: *sockaddr_in) -> libc::c_int { + return rustrt::rust_uv_tcp_getpeername(tcp_handle_ptr, name); +} + +pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, + name: *sockaddr_in6) ->libc::c_int { + return rustrt::rust_uv_tcp_getpeername6(tcp_handle_ptr, name); +} + pub unsafe fn listen(stream: *T, backlog: libc::c_int, cb: *u8) -> libc::c_int { return rustrt::rust_uv_listen(stream as *libc::c_void, backlog, cb); @@ -857,6 +873,12 @@ pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str { } } } +pub unsafe fn ip4_port(src: &sockaddr_in) -> uint { + rustrt::rust_uv_ip4_port(to_unsafe_ptr(src)) as uint +} +pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint { + rustrt::rust_uv_ip6_port(to_unsafe_ptr(src)) as uint +} pub unsafe fn timer_init(loop_ptr: *libc::c_void, timer_ptr: *uv_timer_t) -> libc::c_int { diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 706e8ff43807..c34fd166baec 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -269,6 +269,20 @@ rust_uv_tcp_bind6 return uv_tcp_bind6(tcp_server, addr); } +extern "C" int +rust_uv_tcp_getpeername +(uv_tcp_t* handle, sockaddr_in* name) { + int namelen = sizeof(sockaddr_in); + return uv_tcp_getpeername(handle, (sockaddr*)name, &namelen); +} + +extern "C" int +rust_uv_tcp_getpeername6 +(uv_tcp_t* handle, sockaddr_in6* name) { + int namelen = sizeof(sockaddr_in6); + return uv_tcp_getpeername(handle, (sockaddr*)name, &namelen); +} + extern "C" int rust_uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { @@ -480,6 +494,14 @@ rust_uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) { int result = uv_ip6_name(src, dst, size); return result; } +extern "C" unsigned int +rust_uv_ip4_port(struct sockaddr_in* src) { + return ntohs(src->sin_port); +} +extern "C" unsigned int +rust_uv_ip6_port(struct sockaddr_in6* src) { + return ntohs(src->sin6_port); +} extern "C" uintptr_t* rust_uv_get_kernel_global_chan_ptr() { From 79e538d32ab33604a8288e7b76c875ff075743d2 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Fri, 19 Oct 2012 22:51:33 -0400 Subject: [PATCH 264/292] uv: use just getpeername for both ipv4 and ipv6. --- src/libstd/net_tcp.rs | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 94293c3aa41b..86b3d6ba08f3 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -134,6 +134,10 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, stream_handle_ptr: stream_handle_ptr, connect_req: uv::ll::connect_t(), write_req: uv::ll::write_t(), + ipv6: match input_ip { + ip::Ipv4(_) => { false } + ip::Ipv6(_) => { true } + }, iotask: iotask }; let socket_data_ptr = ptr::addr_of(&(*socket_data)); @@ -475,6 +479,7 @@ pub fn accept(new_conn: TcpNewConnection) stream_handle_ptr : stream_handle_ptr, connect_req : uv::ll::connect_t(), write_req : uv::ll::write_t(), + ipv6: (*server_data_ptr).ipv6, iotask : iotask }; let client_socket_data_ptr = ptr::addr_of(&(*client_socket_data)); @@ -590,6 +595,10 @@ fn listen_common(host_ip: ip::IpAddr, port: uint, backlog: uint, kill_ch: kill_ch, on_connect_cb: move on_connect_cb, iotask: iotask, + ipv6: match host_ip { + ip::Ipv4(_) => { false } + ip::Ipv6(_) => { true } + }, mut active: true }; let server_data_ptr = ptr::addr_of(&server_data); @@ -748,18 +757,17 @@ impl TcpSocket { } pub fn getpeername() -> ip::IpAddr { unsafe { - let addr = uv::ll::ip4_addr("", 0); - uv::ll::tcp_getpeername(self.socket_data.stream_handle_ptr, - ptr::addr_of(&addr)); - ip::Ipv4(move addr) - } - } - pub fn getpeername6() -> ip::IpAddr { - unsafe { - let addr = uv::ll::ip6_addr("", 0); - uv::ll::tcp_getpeername6(self.socket_data.stream_handle_ptr, - ptr::addr_of(&addr)); - ip::Ipv6(move addr) + if self.socket_data.ipv6 { + let addr = uv::ll::ip6_addr("", 0); + uv::ll::tcp_getpeername6(self.socket_data.stream_handle_ptr, + ptr::addr_of(&addr)); + ip::Ipv6(move addr) + } else { + let addr = uv::ll::ip4_addr("", 0); + uv::ll::tcp_getpeername(self.socket_data.stream_handle_ptr, + ptr::addr_of(&addr)); + ip::Ipv4(move addr) + } } } } @@ -1019,6 +1027,7 @@ type TcpListenFcData = { kill_ch: comm::Chan>, on_connect_cb: fn~(*uv::ll::uv_tcp_t), iotask: IoTask, + ipv6: bool, mut active: bool }; @@ -1217,6 +1226,7 @@ type TcpSocketData = { stream_handle_ptr: *uv::ll::uv_tcp_t, connect_req: uv::ll::uv_connect_t, write_req: uv::ll::uv_write_t, + ipv6: bool, iotask: IoTask }; From 781f8cbe4e5f729907d38cb4de8fc407c1bcb23e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 19:38:31 -0400 Subject: [PATCH 265/292] std: Add test for getpeername --- src/libstd/net_tcp.rs | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 86b3d6ba08f3..351b31dcfbc2 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -1249,6 +1249,10 @@ mod test { impl_gl_tcp_ipv4_server_and_client(); } #[test] + fn test_gl_tcp_get_peer_name() unsafe { + impl_gl_tcp_ipv4_get_peer_name(); + } + #[test] fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { impl_gl_tcp_ipv4_client_error_connection_refused(); } @@ -1275,6 +1279,11 @@ mod test { } #[test] #[ignore(cfg(target_os = "linux"))] + fn test_gl_tcp_get_peer_name() unsafe { + impl_gl_tcp_ipv4_get_peer_name(); + } + #[test] + #[ignore(cfg(target_os = "linux"))] fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { impl_gl_tcp_ipv4_client_error_connection_refused(); } @@ -1342,6 +1351,52 @@ mod test { assert str::contains(actual_req, expected_req); assert str::contains(actual_resp, expected_resp); } + fn impl_gl_tcp_ipv4_get_peer_name() { + let hl_loop = uv::global_loop::get(); + let server_ip = ~"127.0.0.1"; + let server_port = 8889u; + let expected_resp = ~"pong"; + + let server_result_po = core::comm::Port::<~str>(); + let server_result_ch = core::comm::Chan(&server_result_po); + + let cont_po = core::comm::Port::<()>(); + let cont_ch = core::comm::Chan(&cont_po); + // server + do task::spawn_sched(task::ManualThreads(1u)) { + let actual_req = do comm::listen |server_ch| { + run_tcp_test_server( + server_ip, + server_port, + expected_resp, + server_ch, + cont_ch, + hl_loop) + }; + server_result_ch.send(actual_req); + }; + core::comm::recv(cont_po); + // client + log(debug, ~"server started, firing up client.."); + do core::comm::listen |client_ch| { + let server_ip_addr = ip::v4::parse_addr(server_ip); + let iotask = uv::global_loop::get(); + let connect_result = connect(move server_ip_addr, server_port, + iotask); + + let sock = result::unwrap(move connect_result); + + // This is what we are actually testing! + assert net::ip::format_addr(&sock.getpeername()) == ~"127.0.0.1"; + assert net::ip::get_port(&sock.getpeername()) == 8889; + + // Fulfill the protocol the test server expects + let resp_bytes = str::to_bytes(~"ping"); + tcp_write_single(&sock, resp_bytes); + let read_result = sock.read(0u); + client_ch.send(str::from_bytes(read_result.get())); + }; + } fn impl_gl_tcp_ipv4_client_error_connection_refused() { let hl_loop = uv::global_loop::get(); let server_ip = ~"127.0.0.1"; From 9555ee790f36033a1f2356cef7c115d5a588a8de Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Sat, 20 Oct 2012 19:54:08 -0400 Subject: [PATCH 266/292] std: rename getpeername to get_peer_addr --- src/libstd/net_tcp.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 351b31dcfbc2..765c9ecdb03b 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -755,7 +755,7 @@ impl TcpSocket { -> future::Future> { write_future(&self, raw_write_data) } - pub fn getpeername() -> ip::IpAddr { + pub fn get_peer_addr() -> ip::IpAddr { unsafe { if self.socket_data.ipv6 { let addr = uv::ll::ip6_addr("", 0); @@ -1249,8 +1249,8 @@ mod test { impl_gl_tcp_ipv4_server_and_client(); } #[test] - fn test_gl_tcp_get_peer_name() unsafe { - impl_gl_tcp_ipv4_get_peer_name(); + fn test_gl_tcp_get_peer_addr() unsafe { + impl_gl_tcp_ipv4_get_peer_addr(); } #[test] fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { @@ -1279,8 +1279,8 @@ mod test { } #[test] #[ignore(cfg(target_os = "linux"))] - fn test_gl_tcp_get_peer_name() unsafe { - impl_gl_tcp_ipv4_get_peer_name(); + fn test_gl_tcp_get_peer_addr() unsafe { + impl_gl_tcp_ipv4_get_peer_addr(); } #[test] #[ignore(cfg(target_os = "linux"))] @@ -1351,7 +1351,7 @@ mod test { assert str::contains(actual_req, expected_req); assert str::contains(actual_resp, expected_resp); } - fn impl_gl_tcp_ipv4_get_peer_name() { + fn impl_gl_tcp_ipv4_get_peer_addr() { let hl_loop = uv::global_loop::get(); let server_ip = ~"127.0.0.1"; let server_port = 8889u; @@ -1387,8 +1387,8 @@ mod test { let sock = result::unwrap(move connect_result); // This is what we are actually testing! - assert net::ip::format_addr(&sock.getpeername()) == ~"127.0.0.1"; - assert net::ip::get_port(&sock.getpeername()) == 8889; + assert net::ip::format_addr(&sock.get_peer_addr()) == ~"127.0.0.1"; + assert net::ip::get_port(&sock.get_peer_addr()) == 8889; // Fulfill the protocol the test server expects let resp_bytes = str::to_bytes(~"ping"); @@ -1592,8 +1592,11 @@ mod test { ~"SERVER/WORKER: send on cont ch"); cont_ch.send(()); let sock = result::unwrap(move accept_result); + let peer_addr = sock.get_peer_addr(); log(debug, ~"SERVER: successfully accepted"+ - ~"connection!"); + fmt!(" connection from %s:%u", + ip::format_addr(&peer_addr), + ip::get_port(&peer_addr))); let received_req_bytes = read(&sock, 0u); match move received_req_bytes { result::Ok(move data) => { From 8dd8136f912bc0d54d6d2bf3afa31190aeb9b258 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 17:24:27 -0700 Subject: [PATCH 267/292] std: Use unique ports in tcp tests --- src/libstd/net_tcp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 765c9ecdb03b..1a497a444019 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -1354,7 +1354,7 @@ mod test { fn impl_gl_tcp_ipv4_get_peer_addr() { let hl_loop = uv::global_loop::get(); let server_ip = ~"127.0.0.1"; - let server_port = 8889u; + let server_port = 8887u; let expected_resp = ~"pong"; let server_result_po = core::comm::Port::<~str>(); @@ -1388,7 +1388,7 @@ mod test { // This is what we are actually testing! assert net::ip::format_addr(&sock.get_peer_addr()) == ~"127.0.0.1"; - assert net::ip::get_port(&sock.get_peer_addr()) == 8889; + assert net::ip::get_port(&sock.get_peer_addr()) == 8887; // Fulfill the protocol the test server expects let resp_bytes = str::to_bytes(~"ping"); From 55e40a167426a7e28fc334286ef2b5c47c46e6fd Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 17:41:34 -0700 Subject: [PATCH 268/292] Add new uv functions to rustrt.def.in --- src/rt/rustrt.def.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 890aa352c927..6a2bdd622cba 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -204,3 +204,7 @@ tdefl_compress_mem_to_heap tinfl_decompress_mem_to_heap rust_annihilate_box rust_gc_metadata +rust_uv_ip4_port +rust_uv_ip6_port +rust_uv_tcp_getpeername +rust_uv_tcp_getpeername6 \ No newline at end of file From 4174688dd48f4967e08c0aecc7a2a90dc28a56da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Br=C3=BCschweiler?= Date: Tue, 9 Oct 2012 19:42:26 +0200 Subject: [PATCH 269/292] libsyntax: adapt the pretty printer for the new fixed size array syntax `[int]/5` -> `[int * 5]` --- src/libsyntax/print/pprust.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3fc2bcda9018..807a78b31226 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -399,9 +399,21 @@ fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) { } ast::ty_path(path, _) => print_path(s, path, print_colons), ast::ty_fixed_length(t, v) => { - print_type(s, t); - word(s.s, ~"/"); + word(s.s, ~"["); + match t.node { + ast::ty_vec(mt) => { + match mt.mutbl { + ast::m_mutbl => word_space(s, ~"mut"), + ast::m_const => word_space(s, ~"const"), + ast::m_imm => () + } + print_type(s, mt.ty); + } + _ => fail ~"ty_fixed_length can only contain ty_vec as type" + } + word(s.s, ~" * "); print_vstore(s, ast::vstore_fixed(v)); + word(s.s, ~"]"); } ast::ty_mac(_) => { fail ~"print_type doesn't know how to print a ty_mac"; From ac81fff22926d464f7a90f14c4c8f846569e75e0 Mon Sep 17 00:00:00 2001 From: Ben Striegel Date: Wed, 10 Oct 2012 00:28:04 -0400 Subject: [PATCH 270/292] Remove old fixed-length vector syntax --- src/libcore/hash.rs | 136 +++++++++--------- src/libcore/pipes.rs | 4 +- src/libcore/uint-template.rs | 14 +- src/libstd/arena.rs | 4 +- src/libsyntax/ast.rs | 5 +- src/libsyntax/parse/parser.rs | 9 +- src/rustc/driver/rustc.rs | 2 +- src/rustc/middle/const_eval.rs | 2 +- src/rustc/middle/trans/common.rs | 4 +- src/rustc/middle/trans/tvec.rs | 2 +- src/rustc/middle/typeck/check.rs | 2 +- src/test/compile-fail/evec-subtyping.rs | 6 +- src/test/run-pass/assignability-trait.rs | 2 +- .../run-pass/borrowck-fixed-length-vecs.rs | 4 +- .../run-pass/const-fields-and-indexing.rs | 4 +- src/test/run-pass/const-vecs-and-slices.rs | 4 +- src/test/run-pass/evec-internal-boxes.rs | 6 +- src/test/run-pass/evec-internal.rs | 12 +- src/test/run-pass/fixed_length_copy.rs | 2 +- src/test/run-pass/fixed_length_vec_glue.rs | 2 +- src/test/run-pass/iter-all.rs | 6 +- src/test/run-pass/iter-any.rs | 6 +- src/test/run-pass/iter-contains.rs | 10 +- src/test/run-pass/iter-count.rs | 8 +- src/test/run-pass/iter-eachi.rs | 2 +- src/test/run-pass/iter-filter-to-vec.rs | 4 +- src/test/run-pass/iter-foldl.rs | 4 +- src/test/run-pass/iter-map-to-vec.rs | 4 +- src/test/run-pass/iter-min-max.rs | 8 +- src/test/run-pass/iter-to-vec.rs | 2 +- .../run-pass/pipe-presentation-examples.rs | 2 +- .../run-pass/regions-borrow-evec-fixed.rs | 2 +- src/test/run-pass/select-macro.rs | 2 +- 33 files changed, 135 insertions(+), 151 deletions(-) diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index 1b4996a683d1..e3bbfbc4129d 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -156,7 +156,7 @@ struct SipState { mut v1: u64, mut v2: u64, mut v3: u64, - tail: [mut u8]/8, // unprocessed bytes + tail: [mut u8 * 8], // unprocessed bytes mut ntail: uint, // how many bytes in tail are valid } @@ -359,72 +359,72 @@ impl &SipState : Streaming { #[test] pub fn test_siphash() { - let vecs : [[u8]/8]/64 = [ - [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ]/_, - [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ]/_, - [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ]/_, - [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ]/_, - [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ]/_, - [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ]/_, - [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ]/_, - [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ]/_, - [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ]/_, - [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ]/_, - [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ]/_, - [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ]/_, - [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ]/_, - [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ]/_, - [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ]/_, - [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ]/_, - [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ]/_, - [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ]/_, - [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ]/_, - [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ]/_, - [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ]/_, - [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ]/_, - [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ]/_, - [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ]/_, - [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ]/_, - [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ]/_, - [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ]/_, - [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ]/_, - [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ]/_, - [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ]/_, - [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ]/_, - [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ]/_, - [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ]/_, - [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ]/_, - [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ]/_, - [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ]/_, - [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ]/_, - [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ]/_, - [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ]/_, - [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ]/_, - [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ]/_, - [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ]/_, - [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ]/_, - [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ]/_, - [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ]/_, - [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ]/_, - [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ]/_, - [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ]/_, - [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ]/_, - [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ]/_, - [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ]/_, - [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ]/_, - [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ]/_, - [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ]/_, - [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ]/_, - [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ]/_, - [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ]/_, - [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ]/_, - [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ]/_, - [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ]/_, - [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ]/_, - [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ]/_, - [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ]/_, - [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]/_ - ]/_; + let vecs : [[u8 * 8] * 64] = [ + [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ], + [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ], + [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ], + [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ], + [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ], + [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ], + [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ], + [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ], + [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ], + [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ], + [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ], + [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ], + [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ], + [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ], + [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ], + [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ], + [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ], + [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ], + [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ], + [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ], + [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ], + [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ], + [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ], + [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ], + [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ], + [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ], + [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ], + [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ], + [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ], + [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ], + [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ], + [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ], + [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ], + [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ], + [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ], + [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ], + [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ], + [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ], + [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ], + [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ], + [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ], + [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ], + [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ], + [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ], + [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ], + [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ], + [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ], + [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ], + [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ], + [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ], + [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ], + [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ], + [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ], + [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ], + [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ], + [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ], + [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ], + [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ], + [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ], + [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ], + [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ], + [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ], + [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ], + [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ] + ]; let k0 = 0x_07_06_05_04_03_02_01_00_u64; let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64; @@ -433,7 +433,7 @@ pub fn test_siphash() { let stream_inc = &State(k0,k1); let stream_full = &State(k0,k1); - fn to_hex_str(r: &[u8]/8) -> ~str { + fn to_hex_str(r: &[u8 * 8]) -> ~str { let mut s = ~""; for vec::each(*r) |b| { s += uint::to_str(*b as uint, 16u); diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index e77cb69b0565..3f8de19498f6 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -667,7 +667,7 @@ pub fn select2( -> Either<(Option, RecvPacketBuffered), (RecvPacketBuffered, Option)> { - let i = wait_many([a.header(), b.header()]/_); + let i = wait_many([a.header(), b.header()]); match i { 0 => Left((try_recv(move a), move b)), @@ -693,7 +693,7 @@ pub fn selecti(endpoints: &[T]) -> uint { /// Returns 0 or 1 depending on which endpoint is ready to receive pub fn select2i(a: &A, b: &B) -> Either<(), ()> { - match wait_many([a.header(), b.header()]/_) { + match wait_many([a.header(), b.header()]) { 0 => Left(()), 1 => Right(()), _ => fail ~"wait returned unexpected index" diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index 00dd9be76db0..3199262ae163 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -187,19 +187,7 @@ pub pure fn to_str_bytes(neg: bool, num: T, radix: uint, // Enough room to hold any number in any radix. // Worst case: 64-bit number, binary-radix, with // a leading negative sign = 65 bytes. - let buf : [mut u8]/65 = - [mut - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8, - - 0u8,0u8,0u8,0u8,0u8 - ]/65; + let buf : [mut u8 * 65] = [mut 0u8, ..65]; // FIXME (#2649): post-snapshot, you can do this without the raw // pointers and unsafe bits, and the codegen will prove it's all diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs index 6a2ac88f7143..9f40794b28a7 100644 --- a/src/libstd/arena.rs +++ b/src/libstd/arena.rs @@ -244,7 +244,7 @@ fn test_arena_destructors() { do arena.alloc { @i }; // Allocate something with funny size and alignment, to keep // things interesting. - do arena.alloc { [0u8, 1u8, 2u8]/3 }; + do arena.alloc { [0u8, 1u8, 2u8] }; } } @@ -258,7 +258,7 @@ fn test_arena_destructors_fail() { do arena.alloc { @i }; // Allocate something with funny size and alignment, to keep // things interesting. - do arena.alloc { [0u8, 1u8, 2u8]/3 }; + do arena.alloc { [0u8, 1u8, 2u8] }; } // Now, fail while allocating do arena.alloc::<@int> { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f494d5648168..010c604dd1ac 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -462,7 +462,7 @@ impl proto : cmp::Eq { #[auto_deserialize] enum vstore { // FIXME (#3469): Change uint to @expr (actually only constant exprs) - vstore_fixed(Option), // [1,2,3,4]/_ or 4 + vstore_fixed(Option), // [1,2,3,4] vstore_uniq, // ~[1,2,3,4] vstore_box, // @[1,2,3,4] vstore_slice(@region) // &[1,2,3,4](foo)? @@ -472,7 +472,8 @@ enum vstore { #[auto_deserialize] enum expr_vstore { // FIXME (#3469): Change uint to @expr (actually only constant exprs) - expr_vstore_fixed(Option), // [1,2,3,4]/_ or 4 + expr_vstore_fixed(Option), // [1,2,3,4] +>>>>>>> Remove old fixed-length vector syntax expr_vstore_uniq, // ~[1,2,3,4] expr_vstore_box, // @[1,2,3,4] expr_vstore_slice // &[1,2,3,4] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8636c51b369d..46905b8fe01f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -207,12 +207,7 @@ fn Parser(sess: parse_sess, cfg: ast::crate_cfg, token: tok0.tok, span: span0, last_span: span0, - buffer: [mut - {tok: tok0.tok, sp: span0}, - {tok: tok0.tok, sp: span0}, - {tok: tok0.tok, sp: span0}, - {tok: tok0.tok, sp: span0} - ]/4, + buffer: [mut {tok: tok0.tok, sp: span0}, ..4], buffer_start: 0, buffer_end: 0, restriction: UNRESTRICTED, @@ -231,7 +226,7 @@ struct Parser { mut token: token::Token, mut span: span, mut last_span: span, - mut buffer: [mut {tok: token::Token, sp: span}]/4, + mut buffer: [mut {tok: token::Token, sp: span} * 4], mut buffer_start: int, mut buffer_end: int, mut restriction: restriction, diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index e52f34f4645d..a6de92ceeb3e 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -233,7 +233,7 @@ fn monitor(+f: fn~(diagnostic::emitter)) { ~"try running with RUST_LOG=rustc=0,::rt::backtrace \ to get further details and report the results \ to github.com/mozilla/rust/issues" - ]/_.each |note| { + ].each |note| { diagnostic::emit(None, *note, diagnostic::note) } } diff --git a/src/rustc/middle/const_eval.rs b/src/rustc/middle/const_eval.rs index ea7b08140f39..d0296ebd2e54 100644 --- a/src/rustc/middle/const_eval.rs +++ b/src/rustc/middle/const_eval.rs @@ -19,7 +19,7 @@ use ast::*; // target uses". This _includes_ integer-constants, plus the following // constructors: // -// fixed-size vectors and strings: []/_ and ""/_ +// fixed-size vectors and strings: [] and ""/_ // vector and string slices: &[] and &"" // tuples: (,) // records: {...} diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 931e82d5be98..554a533e110d 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -1310,13 +1310,13 @@ fn dummy_substs(tps: ~[ty::t]) -> ty::substs { tps: tps} } -fn struct_field(index: uint) -> [uint]/3 { +fn struct_field(index: uint) -> [uint * 3] { //! The GEPi sequence to access a field of a record/struct. [0, 0, index] } -fn struct_dtor() -> [uint]/2 { +fn struct_dtor() -> [uint * 2] { //! The GEPi sequence to access the dtor of a struct. [0, 1] diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index 149c6ea532d4..bfc172db3148 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -140,7 +140,7 @@ fn trans_fixed_vstore(bcx: block, { //! // - // [...]/_ allocates a fixed-size array and moves it around "by value". + // [...] allocates a fixed-size array and moves it around "by value". // In this case, it means that the caller has already given us a location // to store the array of the suitable size, so all we have to do is // generate the content. diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 6de249ebc68f..5f9e584fa7b9 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1019,7 +1019,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // functions. This is so that we have more information about the types // of arguments when we typecheck the functions. This isn't really the // right way to do this. - for [false, true]/_.each |check_blocks| { + for [false, true].each |check_blocks| { let check_blocks = *check_blocks; debug!("check_blocks=%b", check_blocks); diff --git a/src/test/compile-fail/evec-subtyping.rs b/src/test/compile-fail/evec-subtyping.rs index 2eabfa0c48c6..e5e9aa0c2579 100644 --- a/src/test/compile-fail/evec-subtyping.rs +++ b/src/test/compile-fail/evec-subtyping.rs @@ -1,6 +1,6 @@ fn wants_box(x: @[uint]) { } fn wants_uniq(x: ~[uint]) { } -fn wants_three(x: [uint]/3) { } +fn wants_three(x: [uint * 3]) { } fn has_box(x: @[uint]) { wants_box(x); @@ -14,13 +14,13 @@ fn has_uniq(x: ~[uint]) { wants_three(x); //~ ERROR [] storage differs: expected 3 but found ~ } -fn has_three(x: [uint]/3) { +fn has_three(x: [uint * 3]) { wants_box(x); //~ ERROR [] storage differs: expected @ but found 3 wants_uniq(x); //~ ERROR [] storage differs: expected ~ but found 3 wants_three(x); } -fn has_four(x: [uint]/4) { +fn has_four(x: [uint * 4]) { wants_box(x); //~ ERROR [] storage differs: expected @ but found 4 wants_uniq(x); //~ ERROR [] storage differs: expected ~ but found 4 wants_three(x); //~ ERROR [] storage differs: expected 3 but found 4 diff --git a/src/test/run-pass/assignability-trait.rs b/src/test/run-pass/assignability-trait.rs index 4652212ce5f4..16e7473fb783 100644 --- a/src/test/run-pass/assignability-trait.rs +++ b/src/test/run-pass/assignability-trait.rs @@ -39,7 +39,7 @@ fn main() { assert length::(x) == vec::len(x); // Now try it with a type that *needs* to be borrowed - let z = [0,1,2,3]/_; + let z = [0,1,2,3]; // Call a method for z.iterate() |y| { assert z[*y] == *y; } // Call a parameterized function diff --git a/src/test/run-pass/borrowck-fixed-length-vecs.rs b/src/test/run-pass/borrowck-fixed-length-vecs.rs index 9d79e28b219d..22862d7e58f1 100644 --- a/src/test/run-pass/borrowck-fixed-length-vecs.rs +++ b/src/test/run-pass/borrowck-fixed-length-vecs.rs @@ -1,5 +1,5 @@ fn main() { - let x = [22]/1; + let x = [22]; let y = &x[0]; assert *y == 22; -} \ No newline at end of file +} diff --git a/src/test/run-pass/const-fields-and-indexing.rs b/src/test/run-pass/const-fields-and-indexing.rs index 387ca032f6a7..a5bcfc93c79b 100644 --- a/src/test/run-pass/const-fields-and-indexing.rs +++ b/src/test/run-pass/const-fields-and-indexing.rs @@ -1,4 +1,4 @@ -const x : [int]/4 = [1,2,3,4]; +const x : [int * 4] = [1,2,3,4]; const p : int = x[2]; const y : &[int] = &[1,2,3,4]; const q : int = y[2]; @@ -17,4 +17,4 @@ fn main() { assert p == 3; assert q == 3; assert t == 20; -} \ No newline at end of file +} diff --git a/src/test/run-pass/const-vecs-and-slices.rs b/src/test/run-pass/const-vecs-and-slices.rs index 9cfee2d5dff9..36327172fabb 100644 --- a/src/test/run-pass/const-vecs-and-slices.rs +++ b/src/test/run-pass/const-vecs-and-slices.rs @@ -1,4 +1,4 @@ -const x : [int]/4 = [1,2,3,4]; +const x : [int * 4] = [1,2,3,4]; const y : &[int] = &[1,2,3,4]; fn main() { @@ -7,4 +7,4 @@ fn main() { assert x[1] == 2; assert x[3] == 4; assert x[3] == y[3]; -} \ No newline at end of file +} diff --git a/src/test/run-pass/evec-internal-boxes.rs b/src/test/run-pass/evec-internal-boxes.rs index ce0fe172cf80..5ad12510b38f 100644 --- a/src/test/run-pass/evec-internal-boxes.rs +++ b/src/test/run-pass/evec-internal-boxes.rs @@ -1,7 +1,7 @@ fn main() { - let x : [@int]/5 = [@1,@2,@3,@4,@5]/5; - let _y : [@int]/5 = [@1,@2,@3,@4,@5]/_; - let mut z = [@1,@2,@3,@4,@5]/_; + let x : [@int * 5] = [@1,@2,@3,@4,@5]; + let _y : [@int * 5] = [@1,@2,@3,@4,@5]; + let mut z = [@1,@2,@3,@4,@5]; z = x; assert *z[0] == 1; assert *z[4] == 5; diff --git a/src/test/run-pass/evec-internal.rs b/src/test/run-pass/evec-internal.rs index 789660c11f0f..7ee72272e0ba 100644 --- a/src/test/run-pass/evec-internal.rs +++ b/src/test/run-pass/evec-internal.rs @@ -4,16 +4,16 @@ // Doesn't work; needs a design decision. fn main() { - let x : [int]/5 = [1,2,3,4,5]/5; - let _y : [int]/5 = [1,2,3,4,5]/_; - let mut z = [1,2,3,4,5]/_; + let x : [int * 5] = [1,2,3,4,5]; + let _y : [int * 5] = [1,2,3,4,5]; + let mut z = [1,2,3,4,5]; z = x; assert z[0] == 1; assert z[4] == 5; - let a : [int]/5 = [1,1,1,1,1]/_; - let b : [int]/5 = [2,2,2,2,2]/_; - let c : [int]/5 = [2,2,2,2,3]/_; + let a : [int * 5] = [1,1,1,1,1]; + let b : [int * 5] = [2,2,2,2,2]; + let c : [int * 5] = [2,2,2,2,3]; log(debug, a); diff --git a/src/test/run-pass/fixed_length_copy.rs b/src/test/run-pass/fixed_length_copy.rs index 5bf6eb9a44d4..ca42fc35f2ba 100644 --- a/src/test/run-pass/fixed_length_copy.rs +++ b/src/test/run-pass/fixed_length_copy.rs @@ -3,7 +3,7 @@ // are implicitly copyable #[deny(implicit_copies)] fn main() { - let arr = [1,2,3]/3; + let arr = [1,2,3]; let arr2 = arr; assert(arr[1] == 2); assert(arr2[2] == 3); diff --git a/src/test/run-pass/fixed_length_vec_glue.rs b/src/test/run-pass/fixed_length_vec_glue.rs index 8be0b1b0c432..d9488c5abd88 100644 --- a/src/test/run-pass/fixed_length_vec_glue.rs +++ b/src/test/run-pass/fixed_length_vec_glue.rs @@ -1,5 +1,5 @@ fn main() { - let arr = [1,2,3]/3; + let arr = [1,2,3]; let struc = {a: 13u8, b: arr, c: 42}; let s = sys::log_str(&struc); assert(s == ~"{ a: 13, b: [ 1, 2, 3 ], c: 42 }"); diff --git a/src/test/run-pass/iter-all.rs b/src/test/run-pass/iter-all.rs index 75334db86cc6..b5c10fd2c812 100644 --- a/src/test/run-pass/iter-all.rs +++ b/src/test/run-pass/iter-all.rs @@ -1,9 +1,9 @@ fn is_even(x: &uint) -> bool { (*x % 2) == 0 } fn main() { - assert ![1u, 2u]/_.all(is_even); - assert [2u, 4u]/_.all(is_even); - assert []/_.all(is_even); + assert ![1u, 2u].all(is_even); + assert [2u, 4u].all(is_even); + assert [].all(is_even); assert !Some(1u).all(is_even); assert Some(2u).all(is_even); diff --git a/src/test/run-pass/iter-any.rs b/src/test/run-pass/iter-any.rs index 22057b74a414..f964eda54a5a 100644 --- a/src/test/run-pass/iter-any.rs +++ b/src/test/run-pass/iter-any.rs @@ -1,9 +1,9 @@ fn is_even(x: &uint) -> bool { (*x % 2) == 0 } fn main() { - assert ![1u, 3u]/_.any(is_even); - assert [1u, 2u]/_.any(is_even); - assert ![]/_.any(is_even); + assert ![1u, 3u].any(is_even); + assert [1u, 2u].any(is_even); + assert ![].any(is_even); assert !Some(1).any(is_even); assert Some(2).any(is_even); diff --git a/src/test/run-pass/iter-contains.rs b/src/test/run-pass/iter-contains.rs index 6036b5b2d24b..31fa52175aad 100644 --- a/src/test/run-pass/iter-contains.rs +++ b/src/test/run-pass/iter-contains.rs @@ -1,9 +1,9 @@ fn main() { - assert []/_.contains(&22u) == false; - assert [1u, 3u]/_.contains(&22u) == false; - assert [22u, 1u, 3u]/_.contains(&22u) == true; - assert [1u, 22u, 3u]/_.contains(&22u) == true; - assert [1u, 3u, 22u]/_.contains(&22u) == true; + assert [].contains(&22u) == false; + assert [1u, 3u].contains(&22u) == false; + assert [22u, 1u, 3u].contains(&22u) == true; + assert [1u, 22u, 3u].contains(&22u) == true; + assert [1u, 3u, 22u].contains(&22u) == true; assert None.contains(&22u) == false; assert Some(1u).contains(&22u) == false; assert Some(22u).contains(&22u) == true; diff --git a/src/test/run-pass/iter-count.rs b/src/test/run-pass/iter-count.rs index 0b6f94367be3..26aa26b4c8db 100644 --- a/src/test/run-pass/iter-count.rs +++ b/src/test/run-pass/iter-count.rs @@ -1,8 +1,8 @@ fn main() { - assert []/_.count(&22u) == 0u; - assert [1u, 3u]/_.count(&22u) == 0u; - assert [22u, 1u, 3u]/_.count(&22u) == 1u; - assert [22u, 1u, 22u]/_.count(&22u) == 2u; + assert [].count(&22u) == 0u; + assert [1u, 3u].count(&22u) == 0u; + assert [22u, 1u, 3u].count(&22u) == 1u; + assert [22u, 1u, 22u].count(&22u) == 2u; assert None.count(&22u) == 0u; assert Some(1u).count(&22u) == 0u; assert Some(22u).count(&22u) == 1u; diff --git a/src/test/run-pass/iter-eachi.rs b/src/test/run-pass/iter-eachi.rs index 9ae3cc43913b..4c85e6ca3af4 100644 --- a/src/test/run-pass/iter-eachi.rs +++ b/src/test/run-pass/iter-eachi.rs @@ -1,6 +1,6 @@ fn main() { let mut c = 0u; - for [1u, 2u, 3u, 4u, 5u]/_.eachi |i, v| { + for [1u, 2u, 3u, 4u, 5u].eachi |i, v| { assert (i + 1u) == *v; c += 1u; } diff --git a/src/test/run-pass/iter-filter-to-vec.rs b/src/test/run-pass/iter-filter-to-vec.rs index f96b18f140a4..000e7c491be1 100644 --- a/src/test/run-pass/iter-filter-to-vec.rs +++ b/src/test/run-pass/iter-filter-to-vec.rs @@ -1,8 +1,8 @@ fn is_even(+x: uint) -> bool { (x % 2) == 0 } fn main() { - assert [1, 3]/_.filter_to_vec(is_even) == ~[]; - assert [1, 2, 3]/_.filter_to_vec(is_even) == ~[2]; + assert [1, 3].filter_to_vec(is_even) == ~[]; + assert [1, 2, 3].filter_to_vec(is_even) == ~[2]; assert None.filter_to_vec(is_even) == ~[]; assert Some(1).filter_to_vec(is_even) == ~[]; assert Some(2).filter_to_vec(is_even) == ~[2]; diff --git a/src/test/run-pass/iter-foldl.rs b/src/test/run-pass/iter-foldl.rs index bbc1673f6864..65b517acf1c1 100644 --- a/src/test/run-pass/iter-foldl.rs +++ b/src/test/run-pass/iter-foldl.rs @@ -1,8 +1,8 @@ fn add(x: &float, y: &uint) -> float { *x + ((*y) as float) } fn main() { - assert [1u, 3u]/_.foldl(20f, add) == 24f; - assert []/_.foldl(20f, add) == 20f; + assert [1u, 3u].foldl(20f, add) == 24f; + assert [].foldl(20f, add) == 20f; assert None.foldl(20f, add) == 20f; assert Some(1u).foldl(20f, add) == 21f; assert Some(2u).foldl(20f, add) == 22f; diff --git a/src/test/run-pass/iter-map-to-vec.rs b/src/test/run-pass/iter-map-to-vec.rs index 2f5359f197f1..208fc5d127ed 100644 --- a/src/test/run-pass/iter-map-to-vec.rs +++ b/src/test/run-pass/iter-map-to-vec.rs @@ -1,8 +1,8 @@ fn inc(+x: uint) -> uint { x + 1 } fn main() { - assert [1, 3]/_.map_to_vec(inc) == ~[2, 4]; - assert [1, 2, 3]/_.map_to_vec(inc) == ~[2, 3, 4]; + assert [1, 3].map_to_vec(inc) == ~[2, 4]; + assert [1, 2, 3].map_to_vec(inc) == ~[2, 3, 4]; assert None.map_to_vec(inc) == ~[]; assert Some(1).map_to_vec(inc) == ~[2]; assert Some(2).map_to_vec(inc) == ~[3]; diff --git a/src/test/run-pass/iter-min-max.rs b/src/test/run-pass/iter-min-max.rs index 23bd7fb05af4..60001c8f7e52 100644 --- a/src/test/run-pass/iter-min-max.rs +++ b/src/test/run-pass/iter-min-max.rs @@ -1,11 +1,11 @@ fn is_even(&&x: uint) -> bool { (x % 2u) == 0u } fn main() { - assert [1u, 3u]/_.min() == 1u; - assert [3u, 1u]/_.min() == 1u; + assert [1u, 3u].min() == 1u; + assert [3u, 1u].min() == 1u; assert Some(1u).min() == 1u; - assert [1u, 3u]/_.max() == 3u; - assert [3u, 1u]/_.max() == 3u; + assert [1u, 3u].max() == 3u; + assert [3u, 1u].max() == 3u; assert Some(3u).max() == 3u; } diff --git a/src/test/run-pass/iter-to-vec.rs b/src/test/run-pass/iter-to-vec.rs index c2f1330b7212..358f484464d5 100644 --- a/src/test/run-pass/iter-to-vec.rs +++ b/src/test/run-pass/iter-to-vec.rs @@ -1,5 +1,5 @@ fn main() { - assert [1u, 3u]/_.to_vec() == ~[1u, 3u]; + assert [1u, 3u].to_vec() == ~[1u, 3u]; let e: ~[uint] = ~[]; assert e.to_vec() == ~[]; assert None::.to_vec() == ~[]; diff --git a/src/test/run-pass/pipe-presentation-examples.rs b/src/test/run-pass/pipe-presentation-examples.rs index 7ce8e6ea73d0..853aba53eda4 100644 --- a/src/test/run-pass/pipe-presentation-examples.rs +++ b/src/test/run-pass/pipe-presentation-examples.rs @@ -56,7 +56,7 @@ macro_rules! select ( -> $next:ident $e:expr),+ } )+ } => { - let index = pipes::selecti([$(($port).header()),+]/_); + let index = pipes::selecti([$(($port).header()),+]); select_if!(index, 0, $( $port => [ $($message$(($($x),+))dont_type_this* -> $next $e),+ ], )+) diff --git a/src/test/run-pass/regions-borrow-evec-fixed.rs b/src/test/run-pass/regions-borrow-evec-fixed.rs index 5a0875109f6c..2526540bde1b 100644 --- a/src/test/run-pass/regions-borrow-evec-fixed.rs +++ b/src/test/run-pass/regions-borrow-evec-fixed.rs @@ -5,6 +5,6 @@ fn foo(x: &[int]) -> int { } fn main() { - let p = [1,2,3,4,5]/_; + let p = [1,2,3,4,5]; assert foo(p) == 1; } diff --git a/src/test/run-pass/select-macro.rs b/src/test/run-pass/select-macro.rs index d6ce85ac3446..271ed99057fc 100644 --- a/src/test/run-pass/select-macro.rs +++ b/src/test/run-pass/select-macro.rs @@ -52,7 +52,7 @@ macro_rules! select ( -> $next:ident $e:expr),+ } )+ } => { - let index = pipes::selecti([$(($port).header()),+]/_); + let index = pipes::selecti([$(($port).header()),+]); select_if!(index, 0 $(, $port => [ $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { move $e }),+ ])+) From 684d945ab78d6779c198dcb4a340b2269b0fb8aa Mon Sep 17 00:00:00 2001 From: Ben Striegel Date: Wed, 10 Oct 2012 23:43:02 -0400 Subject: [PATCH 271/292] Fix a pprint test for fixed-length vecs --- src/test/pretty/blank-lines.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/pretty/blank-lines.rs b/src/test/pretty/blank-lines.rs index 3ef46a721aeb..d677577e4424 100644 --- a/src/test/pretty/blank-lines.rs +++ b/src/test/pretty/blank-lines.rs @@ -1,5 +1,5 @@ // pp-exact -fn f() -> [int]/3 { +fn f() -> [int * 3] { let picard = 0; let data = 1; @@ -7,7 +7,7 @@ fn f() -> [int]/3 { let worf = 2; - let enterprise = [picard, data, worf]/_; + let enterprise = [picard, data, worf]; From 614624a34c7917c76927163ca3d82eef01e1c369 Mon Sep 17 00:00:00 2001 From: Ben Striegel Date: Thu, 11 Oct 2012 22:47:31 -0400 Subject: [PATCH 272/292] No longer parse old fixed-length vec sytnax --- src/libsyntax/parse/parser.rs | 39 +---------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 46905b8fe01f..879df19f11a9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -554,12 +554,7 @@ impl Parser { let sp = mk_sp(lo, self.last_span.hi); return @{id: self.get_id(), - node: match self.maybe_parse_fixed_vstore() { - // Consider a fixed vstore suffix (/N or /_) - None => t, - Some(v) => { - ty_fixed_length(@{id: self.get_id(), node:t, span: sp}, v) - } }, + node: t, span: sp} } @@ -691,23 +686,6 @@ impl Parser { } } - fn maybe_parse_fixed_vstore() -> Option> { - if self.token == token::BINOP(token::SLASH) { - self.bump(); - match copy self.token { - token::UNDERSCORE => { - self.bump(); Some(None) - } - token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => { - self.bump(); Some(Some(i as uint)) - } - _ => None - } - } else { - None - } - } - fn maybe_parse_fixed_vstore_with_star() -> Option> { if self.eat(token::BINOP(token::STAR)) { match copy self.token { @@ -1083,21 +1061,6 @@ impl Parser { ex = expr_lit(@lit); } - // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...) - // only. - match ex { - expr_lit(@{node: lit_str(_), span: _}) | - expr_vec(_, _) => match self.maybe_parse_fixed_vstore() { - None => (), - Some(v) => { - hi = self.span.hi; - ex = expr_vstore(self.mk_expr(lo, hi, ex), - expr_vstore_fixed(v)); - } - }, - _ => () - } - return self.mk_pexpr(lo, hi, ex); } From 41c37d9d0f4bd8ee7f711d47d93e08e5687de3b4 Mon Sep 17 00:00:00 2001 From: Ben Striegel Date: Thu, 11 Oct 2012 23:10:17 -0400 Subject: [PATCH 273/292] ...missed a merge marker on that last rebase --- src/libsyntax/ast.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 010c604dd1ac..9c49c1638bff 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -473,7 +473,6 @@ enum vstore { enum expr_vstore { // FIXME (#3469): Change uint to @expr (actually only constant exprs) expr_vstore_fixed(Option), // [1,2,3,4] ->>>>>>> Remove old fixed-length vector syntax expr_vstore_uniq, // ~[1,2,3,4] expr_vstore_box, // @[1,2,3,4] expr_vstore_slice // &[1,2,3,4] From f3df50f67f2aa6dbdc3e4c35d6eb2ba8e6b37eed Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 16:33:59 -0700 Subject: [PATCH 274/292] Parse and report obsolete fixed-length vector syntax --- src/libsyntax/parse/obsolete.rs | 69 +++++++++++++++++++++++- src/libsyntax/parse/parser.rs | 11 +++- src/test/compile-fail/obsolete-syntax.rs | 11 ++++ 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index c0e01fb19443..1f607d849d96 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -23,7 +23,8 @@ pub enum ObsoleteSyntax { ObsoleteClassTraits, ObsoletePrivSection, ObsoleteModeInFnType, - ObsoleteByMutRefMode + ObsoleteByMutRefMode, + ObsoleteFixedLengthVec, } impl ObsoleteSyntax : cmp::Eq { @@ -99,6 +100,11 @@ impl Parser : ObsoleteReporter { "by-mutable-reference mode", "Declare an argument of type &mut T instead" ), + ObsoleteFixedLengthVec => ( + "fixed-length vector", + "Fixed-length types are now written `[T * N]`, and instances \ + are type-inferred" + ) }; self.report(sp, kind, kind_str, desc); @@ -183,5 +189,66 @@ impl Parser : ObsoleteReporter { false } } + + fn try_parse_obsolete_fixed_vstore() -> Option> { + if self.token == token::BINOP(token::SLASH) { + self.bump(); + match copy self.token { + token::UNDERSCORE => { + self.obsolete(copy self.last_span, + ObsoleteFixedLengthVec); + self.bump(); Some(None) + } + token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => { + self.obsolete(copy self.last_span, + ObsoleteFixedLengthVec); + self.bump(); Some(Some(i as uint)) + } + _ => None + } + } else { + None + } + } + + fn try_convert_ty_to_obsolete_fixed_length_vstore(sp: span, t: ast::ty_) + -> ast::ty_ { + match self.try_parse_obsolete_fixed_vstore() { + // Consider a fixed length vstore suffix (/N or /_) + None => t, + Some(v) => { + ast::ty_fixed_length( + @{id: self.get_id(), node: t, span: sp}, v) + } + } + } + + fn try_convert_expr_to_obsolete_fixed_length_vstore( + lo: uint, hi: uint, ex: ast::expr_ + ) -> (uint, ast::expr_) { + + let mut hi = hi; + let mut ex = ex; + + // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...) + // only. + match ex { + ast::expr_lit(@{node: ast::lit_str(_), span: _}) | + ast::expr_vec(_, _) => { + match self.try_parse_obsolete_fixed_vstore() { + None => (), + Some(v) => { + hi = self.span.hi; + ex = ast::expr_vstore(self.mk_expr(lo, hi, ex), + ast::expr_vstore_fixed(v)); + } + } + } + _ => () + } + + return (hi, ex); + } + } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 879df19f11a9..1ee683bdd088 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -553,9 +553,13 @@ impl Parser { } else { self.fatal(~"expected type"); }; let sp = mk_sp(lo, self.last_span.hi); - return @{id: self.get_id(), - node: t, + return { + let node = + self.try_convert_ty_to_obsolete_fixed_length_vstore(sp, t); + @{id: self.get_id(), + node: node, span: sp} + }; } fn parse_arg_mode() -> mode { @@ -1061,6 +1065,9 @@ impl Parser { ex = expr_lit(@lit); } + let (hi, ex) = + self.try_convert_expr_to_obsolete_fixed_length_vstore(lo, hi, ex); + return self.mk_pexpr(lo, hi, ex); } diff --git a/src/test/compile-fail/obsolete-syntax.rs b/src/test/compile-fail/obsolete-syntax.rs index 9f57e08cdb2f..c8a8bd859615 100644 --- a/src/test/compile-fail/obsolete-syntax.rs +++ b/src/test/compile-fail/obsolete-syntax.rs @@ -56,4 +56,15 @@ fn obsolete_with() { //~^ ERROR obsolete syntax: with } +fn obsolete_fixed_length_vec() { + let foo: [int]/1; + //~^ ERROR obsolete syntax: fixed-length vector + foo = [1]/_; + //~^ ERROR obsolete syntax: fixed-length vector + let foo: [int]/1; + //~^ ERROR obsolete syntax: fixed-length vector + foo = [1]/1; + //~^ ERROR obsolete syntax: fixed-length vector +} + fn main() { } From 8a8fbe3dce7120e476edfa7ca4c0a40671b61cb6 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 16:59:20 -0700 Subject: [PATCH 275/292] Remove remaining uses of old fixed-length vec syntax --- src/test/run-pass/issue-3656.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs index feb7ad1db7a8..330ec59a0a8f 100644 --- a/src/test/run-pass/issue-3656.rs +++ b/src/test/run-pass/issue-3656.rs @@ -5,7 +5,7 @@ use libc::*; struct KEYGEN { - hash_algorithm: [c_uint]/2, + hash_algorithm: [c_uint * 2], count: uint32_t, salt: *c_void, salt_size: uint32_t, From 837875711a8724784e401ee5ef2fecad006a0ca6 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 17:40:21 -0700 Subject: [PATCH 276/292] Remove obsolete fixed-length string test --- src/test/compile-fail/estr-subtyping.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/test/compile-fail/estr-subtyping.rs b/src/test/compile-fail/estr-subtyping.rs index 7e3e29f2b8f5..626e7eff3f7c 100644 --- a/src/test/compile-fail/estr-subtyping.rs +++ b/src/test/compile-fail/estr-subtyping.rs @@ -1,29 +1,23 @@ fn wants_box(x: @str) { } fn wants_uniq(x: ~str) { } -fn wants_three(x: str/3) { } +fn wants_slice(x: &str) { } fn has_box(x: @str) { wants_box(x); wants_uniq(x); //~ ERROR str storage differs: expected ~ but found @ - wants_three(x); //~ ERROR str storage differs: expected 3 but found @ + wants_slice(x); } fn has_uniq(x: ~str) { wants_box(x); //~ ERROR str storage differs: expected @ but found ~ wants_uniq(x); - wants_three(x); //~ ERROR str storage differs: expected 3 but found ~ + wants_slice(x); } -fn has_three(x: str/3) { - wants_box(x); //~ ERROR str storage differs: expected @ but found 3 - wants_uniq(x); //~ ERROR str storage differs: expected ~ but found 3 - wants_three(x); -} - -fn has_four(x: str/4) { - wants_box(x); //~ ERROR str storage differs: expected @ but found 4 - wants_uniq(x); //~ ERROR str storage differs: expected ~ but found 4 - wants_three(x); //~ ERROR str storage differs: expected 3 but found 4 +fn has_slice(x: &str) { + wants_box(x); //~ ERROR str storage differs: expected @ but found & + wants_uniq(x); //~ ERROR str storage differs: expected ~ but found & + wants_slice(x); } fn main() { From 9980f25a029d9c91f24410d00569e8b479b74edd Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 18:06:01 -0700 Subject: [PATCH 277/292] Long lines --- src/libstd/net_tcp.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 1a497a444019..942d52a3ad6b 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -1387,7 +1387,8 @@ mod test { let sock = result::unwrap(move connect_result); // This is what we are actually testing! - assert net::ip::format_addr(&sock.get_peer_addr()) == ~"127.0.0.1"; + assert net::ip::format_addr(&sock.get_peer_addr()) == + ~"127.0.0.1"; assert net::ip::get_port(&sock.get_peer_addr()) == 8887; // Fulfill the protocol the test server expects From 191d16265be6b9db3d48ef87944b7d42b5dffe0d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 18:30:08 -0700 Subject: [PATCH 278/292] std: Shuffle around test ports some more --- src/libstd/uv_ll.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index c12682fcc928..8bf4e9ed3afc 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1484,7 +1484,7 @@ pub mod test { fn impl_uv_tcp_server_and_request() unsafe { let bind_ip = ~"0.0.0.0"; let request_ip = ~"127.0.0.1"; - let port = 8887; + let port = 8886; let kill_server_msg = ~"does a dog have buddha nature?"; let server_resp_msg = ~"mu!"; let client_port = core::comm::Port::<~str>(); From 4edb88112409c111790dacacb06c22de2ef8da06 Mon Sep 17 00:00:00 2001 From: Paul Stansifer Date: Sat, 20 Oct 2012 21:54:25 -0400 Subject: [PATCH 279/292] Talk about ends, rather than means, in macro tutorial introduction. --- doc/tutorial-macros.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/tutorial-macros.md b/doc/tutorial-macros.md index c7e1ada648e9..40cbcacf1e1b 100644 --- a/doc/tutorial-macros.md +++ b/doc/tutorial-macros.md @@ -2,11 +2,11 @@ # Introduction -Functions are the primary tool that programmers can use to build -abstractions. Sometimes, though, programmers want to abstract over -compile-time, syntactic structures rather than runtime values. For example, -the following two code fragments both pattern-match on their input and return -early in one case, doing nothing otherwise: +Functions are the primary tool that programmers can use to build abstractions. +Sometimes, however, programmers want to perform abstractions over things that are not +runtime values. Macros provide a syntactic abstraction. For an example of how this +can be useful, consider the following two code fragments, which both pattern-match +on their input and return early in one case, and do nothing otherwise: ~~~~ # enum t { special_a(uint), special_b(uint) }; From 7c7980196c35023631500ef1e44e4833f60a6c64 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Sun, 21 Oct 2012 03:42:53 -0400 Subject: [PATCH 280/292] Fix ICE stemming from use of unique pointers in unreachable blocks. --- src/rustc/middle/trans/base.rs | 2 +- src/test/run-fail/doublefail.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/test/run-fail/doublefail.rs diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 4c9a006007e7..d0fe4dec687a 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -267,7 +267,7 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, fn non_gc_box_cast(bcx: block, val: ValueRef) -> ValueRef { debug!("non_gc_box_cast"); add_comment(bcx, ~"non_gc_box_cast"); - assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace); + assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace || bcx.unreachable); let non_gc_t = T_ptr(llvm::LLVMGetElementType(val_ty(val))); PointerCast(bcx, val, non_gc_t) } diff --git a/src/test/run-fail/doublefail.rs b/src/test/run-fail/doublefail.rs new file mode 100644 index 000000000000..37beb7b895ed --- /dev/null +++ b/src/test/run-fail/doublefail.rs @@ -0,0 +1,5 @@ +//error-pattern:One +fn main() { + fail ~"One"; + fail ~"Two"; +} \ No newline at end of file From 42c05fe642efa726dc6cde624b40b638741724ee Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 21 Oct 2012 23:02:02 -0700 Subject: [PATCH 281/292] Correct propagation of mutability from components to base in borrowck Fixes #3828. --- src/rustc/middle/borrowck/loan.rs | 70 ++++++++++++++++--- .../borrowck-imm-field-imm-base.rs | 17 +++++ .../borrowck-imm-field-mut-base.rs | 19 +++++ .../borrowck-mut-field-imm-base.rs | 20 ++++++ 4 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 src/test/compile-fail/borrowck-imm-field-imm-base.rs create mode 100644 src/test/compile-fail/borrowck-imm-field-mut-base.rs create mode 100644 src/test/compile-fail/borrowck-mut-field-imm-base.rs diff --git a/src/rustc/middle/borrowck/loan.rs b/src/rustc/middle/borrowck/loan.rs index 7f4f857dae83..71414e6e7245 100644 --- a/src/rustc/middle/borrowck/loan.rs +++ b/src/rustc/middle/borrowck/loan.rs @@ -106,23 +106,26 @@ impl LoanContext { cat_discr(base, _) => { self.loan(base, req_mutbl) } - cat_comp(cmt_base, comp_field(*)) | - cat_comp(cmt_base, comp_index(*)) | - cat_comp(cmt_base, comp_tuple) => { + cat_comp(cmt_base, comp_field(_, m)) | + cat_comp(cmt_base, comp_index(_, m)) => { // For most components, the type of the embedded data is // stable. Therefore, the base structure need only be // const---unless the component must be immutable. In // that case, it must also be embedded in an immutable // location, or else the whole structure could be // overwritten and the component along with it. - self.loan_stable_comp(cmt, cmt_base, req_mutbl) + self.loan_stable_comp(cmt, cmt_base, req_mutbl, m) + } + cat_comp(cmt_base, comp_tuple) => { + // As above. + self.loan_stable_comp(cmt, cmt_base, req_mutbl, m_imm) } cat_comp(cmt_base, comp_variant(enum_did)) => { // For enums, the memory is unstable if there are multiple // variants, because if the enum value is overwritten then // the memory changes type. if ty::enum_is_univariant(self.bccx.tcx, enum_did) { - self.loan_stable_comp(cmt, cmt_base, req_mutbl) + self.loan_stable_comp(cmt, cmt_base, req_mutbl, m_imm) } else { self.loan_unstable_deref(cmt, cmt_base, req_mutbl) } @@ -150,10 +153,59 @@ impl LoanContext { fn loan_stable_comp(&self, cmt: cmt, cmt_base: cmt, - req_mutbl: ast::mutability) -> bckres<()> { - let base_mutbl = match req_mutbl { - m_imm => m_imm, - m_const | m_mutbl => m_const + req_mutbl: ast::mutability, + comp_mutbl: ast::mutability) -> bckres<()> { + // Determine the mutability that the base component must have, + // given the required mutability of the pointer (`req_mutbl`) + // and the declared mutability of the component (`comp_mutbl`). + // This is surprisingly subtle. + // + // Note that the *declared* mutability of the component is not + // necessarily the same as cmt.mutbl, since a component + // declared as immutable but embedded in a mutable context + // becomes mutable. It's best to think of comp_mutbl as being + // either MUTABLE or DEFAULT, not MUTABLE or IMMUTABLE. We + // should really patch up the AST to reflect this distinction. + // + // Let's consider the cases below: + // + // 1. mut required, mut declared: In this case, the base + // component must merely be const. The reason is that it + // does not matter if the base component is borrowed as + // mutable or immutable, as the mutability of the base + // component is overridden in the field declaration itself + // (see `compile-fail/borrowck-mut-field-imm-base.rs`) + // + // 2. mut required, imm declared: This would only be legal if + // the component is embeded in a mutable context. However, + // we detect mismatches between the mutability of the value + // as a whole and the required mutability in `issue_loan()` + // above. In any case, presuming that the component IS + // embedded in a mutable context, both the component and + // the base must be loaned as MUTABLE. This is to ensure + // that there is no loan of the base as IMMUTABLE, which + // would imply that the component must be IMMUTABLE too + // (see `compile-fail/borrowck-imm-field-imm-base.rs`). + // + // 3. mut required, const declared: this shouldn't really be + // possible, since I don't think you can declare a const + // field, but I guess if we DID permit such a declaration + // it would be equivalent to the case above? + // + // 4. imm required, * declared: In this case, the base must be + // immutable. This is true regardless of what was declared + // for this subcomponent, this if the base is mutable, the + // subcomponent must be mutable. + // (see `compile-fail/borrowck-imm-field-mut-base.rs`). + // + // 5. const required, * declared: In this case, the base need + // only be const, since we don't ultimately care whether + // the subcomponent is mutable or not. + let base_mutbl = match (req_mutbl, comp_mutbl) { + (m_mutbl, m_mutbl) => m_const, // (1) + (m_mutbl, _) => m_mutbl, // (2, 3) + (m_imm, _) => m_imm, // (4) + (m_const, _) => m_const // (5) }; do self.loan(cmt_base, base_mutbl).chain |_ok| { diff --git a/src/test/compile-fail/borrowck-imm-field-imm-base.rs b/src/test/compile-fail/borrowck-imm-field-imm-base.rs new file mode 100644 index 000000000000..69ff3b103786 --- /dev/null +++ b/src/test/compile-fail/borrowck-imm-field-imm-base.rs @@ -0,0 +1,17 @@ +struct Foo { + x: uint +} + +struct Bar { + foo: Foo +} + +fn main() { + let mut b = Bar { foo: Foo { x: 3 } }; + let p = &b; //~ NOTE prior loan as immutable granted here + let q = &mut b.foo.x; //~ ERROR loan of mutable local variable as mutable conflicts with prior loan + let r = &p.foo.x; + io::println(fmt!("*r = %u", *r)); + *q += 1; + io::println(fmt!("*r = %u", *r)); +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-imm-field-mut-base.rs b/src/test/compile-fail/borrowck-imm-field-mut-base.rs new file mode 100644 index 000000000000..6b9d93462d94 --- /dev/null +++ b/src/test/compile-fail/borrowck-imm-field-mut-base.rs @@ -0,0 +1,19 @@ +struct Foo { + mut x: uint +} + +struct Bar { + foo: Foo +} + +fn main() { + let mut b = Bar { foo: Foo { x: 3 } }; + let p = &b.foo.x; + let q = &mut b.foo; //~ ERROR loan of mutable field as mutable conflicts with prior loan + //~^ ERROR loan of mutable local variable as mutable conflicts with prior loan + let r = &mut b; //~ ERROR loan of mutable local variable as mutable conflicts with prior loan + io::println(fmt!("*p = %u", *p)); + q.x += 1; + r.foo.x += 1; + io::println(fmt!("*p = %u", *p)); +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-mut-field-imm-base.rs b/src/test/compile-fail/borrowck-mut-field-imm-base.rs new file mode 100644 index 000000000000..f13637ab86a8 --- /dev/null +++ b/src/test/compile-fail/borrowck-mut-field-imm-base.rs @@ -0,0 +1,20 @@ +struct Foo { + mut x: uint +} + +struct Bar { + foo: Foo +} + +fn main() { + let mut b = Bar { foo: Foo { x: 3 } }; + let p = &b; + let q = &mut b.foo.x; + let r = &p.foo.x; //~ ERROR illegal borrow unless pure + let s = &b.foo.x; //~ ERROR loan of mutable field as immutable conflicts with prior loan + io::println(fmt!("*r = %u", *r)); + io::println(fmt!("*r = %u", *s)); + *q += 1; + io::println(fmt!("*r = %u", *r)); + io::println(fmt!("*r = %u", *s)); +} \ No newline at end of file From 46d4bbbae4e52b79c23136b926c1e3b1f187ce4b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 16 Oct 2012 22:14:59 -0700 Subject: [PATCH 282/292] Simplify the AST representation of ty param bounds Change ast::ty_param_bound so that all ty param bounds are represented as traits, with no special cases for Copy/Send/Owned/Const. typeck::collect generates the special cases. A consequence of this is that code using the #[no_core] attribute can't use the Copy kind/trait. Probably not a big deal? As a side effect, any user-defined traits that happen to be called Copy, etc. in the same module override the built-in Copy trait. r=nmatsakis Closes #2284 --- src/libsyntax/ast.rs | 12 ++--- src/libsyntax/ext/auto_serialize.rs | 4 +- src/libsyntax/fold.rs | 5 +- src/libsyntax/parse/parser.rs | 20 ++++---- src/libsyntax/print/pprust.rs | 10 +--- src/libsyntax/visit.rs | 5 +- src/rustc/middle/resolve.rs | 18 +++---- src/rustc/middle/typeck/collect.rs | 49 ++++++++++++------- .../tag-that-dare-not-speak-its-name.rs | 2 +- src/test/run-pass/issue-2284.rs | 1 - 10 files changed, 59 insertions(+), 67 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9c49c1638bff..a3d2fe96b5dc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -123,13 +123,11 @@ const crate_node_id: node_id = 0; #[auto_serialize] #[auto_deserialize] -enum ty_param_bound { - bound_copy, - bound_send, - bound_const, - bound_owned, - bound_trait(@Ty), -} +// The AST represents all type param bounds as types. +// typeck::collect::compute_bounds matches these against +// the "special" built-in traits (see middle::lang_items) and +// detects Copy, Send, Owned, and Const. +enum ty_param_bound = @Ty; #[auto_serialize] #[auto_deserialize] diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 7e5e68ffff90..47e61c26f38d 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -227,7 +227,7 @@ priv impl ext_ctxt { path: @ast::path, bounds: @~[ast::ty_param_bound] ) -> ast::ty_param { - let bound = ast::bound_trait(@{ + let bound = ast::ty_param_bound(@{ id: self.next_id(), node: ast::ty_path(path, self.next_id()), span: span, @@ -366,7 +366,7 @@ fn mk_impl( let mut trait_tps = vec::append( ~[ty_param], do tps.map |tp| { - let t_bound = ast::bound_trait(@{ + let t_bound = ast::ty_param_bound(@{ id: cx.next_id(), node: ast::ty_path(path, cx.next_id()), span: span, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 564debefa253..311928dd4e0c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -131,10 +131,7 @@ fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl { } fn fold_ty_param_bound(tpb: ty_param_bound, fld: ast_fold) -> ty_param_bound { - match tpb { - bound_copy | bound_send | bound_const | bound_owned => tpb, - bound_trait(ty) => bound_trait(fld.fold_ty(ty)) - } + ty_param_bound(fld.fold_ty(*tpb)) } fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1ee683bdd088..925da063ca62 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -24,8 +24,7 @@ use obsolete::{ }; use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move, - bitand, bitor, bitxor, blk, blk_check_mode, bound_const, - bound_copy, bound_send, bound_trait, bound_owned, box, by_copy, + bitand, bitor, bitxor, blk, blk_check_mode, box, by_copy, by_move, by_ref, by_val, capture_clause, capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item, class_immutable, class_mutable, @@ -2295,19 +2294,20 @@ impl Parser { return spanned(lo, hi, bloc); } + fn mk_ty_path(i: ident) -> @Ty { + @{id: self.get_id(), node: ty_path( + ident_to_path(copy self.last_span, i), + self.get_id()), span: self.last_span} + } + fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] { let mut bounds = ~[]; if self.eat(token::COLON) { while is_ident(self.token) { if is_ident(self.token) { - // XXX: temporary until kinds become traits let maybe_bound = match self.token { token::IDENT(copy sid, _) => { match *self.id_to_str(sid) { - ~"Send" => Some(bound_send), - ~"Copy" => Some(bound_copy), - ~"Const" => Some(bound_const), - ~"Owned" => Some(bound_owned), ~"send" | ~"copy" @@ -2317,7 +2317,7 @@ impl Parser { ObsoleteLowerCaseKindBounds); // Bogus value, but doesn't matter, since // is an error - Some(bound_send) + Some(ty_param_bound(self.mk_ty_path(sid))) } _ => None @@ -2332,11 +2332,11 @@ impl Parser { bounds.push(bound); } None => { - bounds.push(bound_trait(self.parse_ty(false))); + bounds.push(ty_param_bound(self.parse_ty(false))); } } } else { - bounds.push(bound_trait(self.parse_ty(false))); + bounds.push(ty_param_bound(self.parse_ty(false))); } } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 807a78b31226..909f59552d4b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1704,17 +1704,11 @@ fn print_arg_mode(s: ps, m: ast::mode) { } fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) { - if vec::len(*bounds) > 0u { + if bounds.is_not_empty() { word(s.s, ~":"); for vec::each(*bounds) |bound| { nbsp(s); - match *bound { - ast::bound_copy => word(s.s, ~"Copy"), - ast::bound_send => word(s.s, ~"Send"), - ast::bound_const => word(s.s, ~"Const"), - ast::bound_owned => word(s.s, ~"Owned"), - ast::bound_trait(t) => print_type(s, t) - } + print_type(s, **bound); } } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 32fcbdfc7589..b45af2d4ae87 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -264,10 +264,7 @@ fn visit_foreign_item(ni: @foreign_item, e: E, v: vt) { fn visit_ty_param_bounds(bounds: @~[ty_param_bound], e: E, v: vt) { for vec::each(*bounds) |bound| { - match *bound { - bound_trait(t) => v.visit_ty(t, e, v), - bound_copy | bound_send | bound_const | bound_owned => () - } + v.visit_ty(**bound, e, v) } } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 33b56d7fabe0..3d2cd6a621cd 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -9,9 +9,9 @@ use middle::pat_util::{pat_bindings}; use syntax::ast::{_mod, add, arm}; use syntax::ast::{bind_by_ref, bind_by_implicit_ref, bind_by_value}; use syntax::ast::{bitand, bitor, bitxor}; -use syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send}; -use syntax::ast::{bound_trait, binding_mode, capture_clause, class_ctor}; -use syntax::ast::{class_dtor, crate, crate_num, decl_item}; +use syntax::ast::{binding_mode, blk, + capture_clause, class_ctor, class_dtor}; +use syntax::ast::{crate, crate_num, decl_item}; use syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn}; use syntax::ast::{def_foreign_mod, def_id, def_label, def_local, def_mod}; use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param}; @@ -39,6 +39,7 @@ use syntax::ast::{trait_ref, tuple_variant_kind, Ty, ty_bool, ty_char}; use syntax::ast::{ty_f, ty_f32, ty_f64, ty_float, ty_i, ty_i16, ty_i32}; use syntax::ast::{ty_i64, ty_i8, ty_int, ty_param, ty_path, ty_str, ty_u}; use syntax::ast::{ty_u16, ty_u32, ty_u64, ty_u8, ty_uint, type_value_ns}; +use syntax::ast::{ty_param_bound}; use syntax::ast::{variant, view_item, view_item_export, view_item_import}; use syntax::ast::{view_item_use, view_path_glob, view_path_list}; use syntax::ast::{view_path_simple, visibility, anonymous, named}; @@ -3764,14 +3765,7 @@ impl Resolver { visitor: ResolveVisitor) { for type_parameters.each |type_parameter| { for type_parameter.bounds.each |bound| { - match *bound { - bound_copy | bound_send | bound_const | bound_owned => { - // Nothing to do. - } - bound_trait(trait_type) => { - self.resolve_type(trait_type, visitor); - } - } + self.resolve_type(**bound, visitor); } } } @@ -4088,7 +4082,7 @@ impl Resolver { let mut result_def = None; // First, check to see whether the name is a primitive type. - if path.idents.len() == 1u { + if path.idents.len() == 1 { let name = path.idents.last(); match self.primitive_type_table diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index a5390d8f293a..e12104a21dad 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -707,28 +707,41 @@ fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item) } } +// Translate the AST's notion of ty param bounds (which are just newtyped Tys) +// to ty's notion of ty param bounds, which can either be user-defined traits, +// or one of the four built-in traits (formerly known as kinds): Const, Copy, +// Owned, and Send. fn compute_bounds(ccx: @crate_ctxt, ast_bounds: @~[ast::ty_param_bound]) -> ty::param_bounds { @do vec::flat_map(*ast_bounds) |b| { - match *b { - ast::bound_send => ~[ty::bound_send], - ast::bound_copy => ~[ty::bound_copy], - ast::bound_const => ~[ty::bound_const], - ast::bound_owned => ~[ty::bound_owned], - ast::bound_trait(t) => { - let ity = ast_ty_to_ty(ccx, empty_rscope, t); - match ty::get(ity).sty { - ty::ty_trait(*) => { - ~[ty::bound_trait(ity)] - } - _ => { - ccx.tcx.sess.span_err( - t.span, ~"type parameter bounds must be \ - trait types"); - ~[] - } + let li = &ccx.tcx.lang_items; + let ity = ast_ty_to_ty(ccx, empty_rscope, **b); + match ty::get(ity).sty { + ty::ty_trait(did, _, _) => { + let d = Some(did); + if d == li.send_trait { + ~[ty::bound_send] + } + else if d == li.copy_trait { + ~[ty::bound_copy] + } + else if d == li.const_trait { + ~[ty::bound_const] + } + else if d == li.owned_trait { + ~[ty::bound_owned] + } + else { + // Must be a user-defined trait + ~[ty::bound_trait(ity)] + } + } + _ => { + ccx.tcx.sess.span_err( + (*b).span, ~"type parameter bounds must be \ + trait types"); + ~[] } - } } } } diff --git a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs index 80a36945097c..f5bd208f00f0 100644 --- a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs +++ b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs @@ -5,7 +5,7 @@ extern mod core; -fn last(v: ~[const T]) -> core::Option { +fn last(v: ~[const &T]) -> core::Option { fail; } diff --git a/src/test/run-pass/issue-2284.rs b/src/test/run-pass/issue-2284.rs index 3689c42253b9..c2c4c03fb8f6 100644 --- a/src/test/run-pass/issue-2284.rs +++ b/src/test/run-pass/issue-2284.rs @@ -1,4 +1,3 @@ -// xfail-test trait Send { fn f(); } From dd66e7549b72575d5d7e06c0173e702e28cdfba7 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 18 Oct 2012 12:20:18 -0700 Subject: [PATCH 283/292] Preliminary support for labeled break/continue for `loop`s This patch adds preliminary middle-end support (liveness and trans) for breaks and `loop`s to `loop` constructs that have labels. while and for loops can't have labels yet. Progress on #2216 --- src/libsyntax/print/pprust.rs | 5 +- src/rustc/middle/liveness.rs | 192 ++++++++++++++++++-------- src/rustc/middle/trans/base.rs | 7 +- src/rustc/middle/trans/common.rs | 1 + src/rustc/middle/trans/controlflow.rs | 32 +++-- src/rustc/middle/trans/expr.rs | 14 +- src/rustc/middle/typeck.rs | 2 +- src/rustc/middle/typeck/check.rs | 26 +++- src/rustc/util/common.rs | 29 ++-- src/test/run-pass/issue-2216.rs | 22 +++ 10 files changed, 232 insertions(+), 98 deletions(-) create mode 100644 src/test/run-pass/issue-2216.rs diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 909f59552d4b..33915c8c0c93 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1180,7 +1180,10 @@ fn print_expr(s: ps, &&expr: @ast::expr) { ast::expr_loop(blk, opt_ident) => { head(s, ~"loop"); space(s.s); - opt_ident.iter(|ident| {print_ident(s, *ident); space(s.s)}); + opt_ident.iter(|ident| { + print_ident(s, *ident); + word_space(s, ~":"); + }); print_block(s, blk); } ast::expr_match(expr, arms) => { diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 89d5c842a9f6..184d694a50c5 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -95,9 +95,9 @@ use dvec::DVec; use std::map::HashMap; use syntax::{visit, ast_util}; -use syntax::print::pprust::{expr_to_str}; +use syntax::print::pprust::{expr_to_str, block_to_str}; use visit::vt; -use syntax::codemap::span; +use syntax::codemap::{span, span_to_str}; use syntax::ast::*; use io::WriterUtil; use capture::{cap_move, cap_drop, cap_copy, cap_ref}; @@ -167,6 +167,16 @@ impl LiveNodeKind : cmp::Eq { pure fn ne(other: &LiveNodeKind) -> bool { !self.eq(other) } } +fn live_node_kind_to_str(lnk: LiveNodeKind, cx: ty::ctxt) -> ~str { + let cm = cx.sess.codemap; + match lnk { + FreeVarNode(s) => fmt!("Free var node [%s]", span_to_str(s, cm)), + ExprNode(s) => fmt!("Expr node [%s]", span_to_str(s, cm)), + VarDefNode(s) => fmt!("Var def node [%s]", span_to_str(s, cm)), + ExitNode => ~"Exit node" + } +} + fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, crate: @crate) -> last_use_map { @@ -277,8 +287,8 @@ fn IrMaps(tcx: ty::ctxt, method_map: typeck::method_map, tcx: tcx, method_map: method_map, last_use_map: last_use_map, - num_live_nodes: 0u, - num_vars: 0u, + num_live_nodes: 0, + num_vars: 0, live_node_map: HashMap(), variable_map: HashMap(), capture_map: HashMap(), @@ -291,9 +301,10 @@ impl IrMaps { fn add_live_node(lnk: LiveNodeKind) -> LiveNode { let ln = LiveNode(self.num_live_nodes); self.lnks.push(lnk); - self.num_live_nodes += 1u; + self.num_live_nodes += 1; - debug!("%s is of kind %?", ln.to_str(), lnk); + debug!("%s is of kind %s", ln.to_str(), + live_node_kind_to_str(lnk, self.tcx)); ln } @@ -308,7 +319,7 @@ impl IrMaps { fn add_variable(vk: VarKind) -> Variable { let v = Variable(self.num_vars); self.var_kinds.push(vk); - self.num_vars += 1u; + self.num_vars += 1; match vk { Local(LocalInfo {id:node_id, _}) | @@ -491,6 +502,10 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) { } expr_fn(_, _, _, cap_clause) | expr_fn_block(_, _, cap_clause) => { + // Interesting control flow (for loops can contain labeled + // breaks or continues) + self.add_live_node_for_node(expr.id, ExprNode(expr.span)); + // Make a live_node for each captured variable, with the span // being the location that the variable is used. This results // in better error messages than just pointing at the closure @@ -571,14 +586,22 @@ const ACC_READ: uint = 1u; const ACC_WRITE: uint = 2u; const ACC_USE: uint = 4u; +type LiveNodeMap = HashMap; + struct Liveness { tcx: ty::ctxt, ir: @IrMaps, s: Specials, successors: ~[mut LiveNode], users: ~[mut users], - mut break_ln: LiveNode, - mut cont_ln: LiveNode, + // The list of node IDs for the nested loop scopes + // we're in. + mut loop_scope: @DVec, + // mappings from loop node ID to LiveNode + // ("break" label should map to loop node ID, + // it probably doesn't now) + break_ln: LiveNodeMap, + cont_ln: LiveNodeMap } fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness { @@ -594,8 +617,9 @@ fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness { vec::to_mut( vec::from_elem(ir.num_live_nodes * ir.num_vars, invalid_users())), - break_ln: invalid_node(), - cont_ln: invalid_node() + loop_scope: @DVec(), + break_ln: HashMap(), + cont_ln: HashMap() } } @@ -691,6 +715,9 @@ impl Liveness { if reader.is_valid() {Some((*self.ir).lnk(reader))} else {None} } + /* + Is this variable live on entry to any of its successor nodes? + */ fn live_on_exit(ln: LiveNode, var: Variable) -> Option { @@ -717,8 +744,8 @@ impl Liveness { } fn indices(ln: LiveNode, op: fn(uint)) { - let node_base_idx = self.idx(ln, Variable(0u)); - for uint::range(0u, self.ir.num_vars) |var_idx| { + let node_base_idx = self.idx(ln, Variable(0)); + for uint::range(0, self.ir.num_vars) |var_idx| { op(node_base_idx + var_idx) } } @@ -735,8 +762,8 @@ impl Liveness { fn write_vars(wr: io::Writer, ln: LiveNode, test: fn(uint) -> LiveNode) { - let node_base_idx = self.idx(ln, Variable(0u)); - for uint::range(0u, self.ir.num_vars) |var_idx| { + let node_base_idx = self.idx(ln, Variable(0)); + for uint::range(0, self.ir.num_vars) |var_idx| { let idx = node_base_idx + var_idx; if test(idx).is_valid() { wr.write_str(~" "); @@ -745,6 +772,28 @@ impl Liveness { } } + fn find_loop_scope(opt_label: Option, id: node_id, sp: span) + -> node_id { + match opt_label { + Some(_) => // Refers to a labeled loop. Use the results of resolve + // to find with one + match self.tcx.def_map.find(id) { + Some(def_label(loop_id)) => loop_id, + _ => self.tcx.sess.span_bug(sp, ~"Label on break/loop \ + doesn't refer to a loop") + }, + None => + // Vanilla 'break' or 'loop', so use the enclosing + // loop scope + if self.loop_scope.len() == 0 { + self.tcx.sess.span_bug(sp, ~"break outside loop"); + } + else { + self.loop_scope.last() + } + } + } + fn ln_str(ln: LiveNode) -> ~str { do io::with_str_writer |wr| { wr.write_str(~"[ln("); @@ -833,18 +882,18 @@ impl Liveness { let idx = self.idx(ln, var); let user = &mut self.users[idx]; - if (acc & ACC_WRITE) != 0u { + if (acc & ACC_WRITE) != 0 { user.reader = invalid_node(); user.writer = ln; } // Important: if we both read/write, must do read second // or else the write will override. - if (acc & ACC_READ) != 0u { + if (acc & ACC_READ) != 0 { user.reader = ln; } - if (acc & ACC_USE) != 0u { + if (acc & ACC_USE) != 0 { self.users[idx].used = true; } @@ -858,10 +907,13 @@ impl Liveness { // if there is a `break` or `again` at the top level, then it's // effectively a return---this only occurs in `for` loops, // where the body is really a closure. + + debug!("compute: using id for block, %s", block_to_str(body, + self.tcx.sess.intr())); + let entry_ln: LiveNode = - self.with_loop_nodes(self.s.exit_ln, self.s.exit_ln, || { - self.propagate_through_fn_block(decl, body) - }); + self.with_loop_nodes(body.node.id, self.s.exit_ln, self.s.exit_ln, + || { self.propagate_through_fn_block(decl, body) }); // hack to skip the loop unless debug! is enabled: debug!("^^ liveness computation results for body %d (entry=%s)", @@ -972,6 +1024,9 @@ impl Liveness { } fn propagate_through_expr(expr: @expr, succ: LiveNode) -> LiveNode { + debug!("propagate_through_expr: %s", + expr_to_str(expr, self.tcx.sess.intr())); + match expr.node { // Interesting cases with control flow or which gen/kill @@ -983,16 +1038,27 @@ impl Liveness { self.propagate_through_expr(e, succ) } - expr_fn(*) | expr_fn_block(*) => { - // the construction of a closure itself is not important, - // but we have to consider the closed over variables. - let caps = (*self.ir).captures(expr); - do (*caps).foldr(succ) |cap, succ| { - self.init_from_succ(cap.ln, succ); - let var = self.variable(cap.var_nid, expr.span); - self.acc(cap.ln, var, ACC_READ | ACC_USE); - cap.ln - } + expr_fn(_, _, blk, _) | expr_fn_block(_, blk, _) => { + debug!("%s is an expr_fn or expr_fn_block", + expr_to_str(expr, self.tcx.sess.intr())); + + /* + The next-node for a break is the successor of the entire + loop. The next-node for a continue is the top of this loop. + */ + self.with_loop_nodes(blk.node.id, succ, + self.live_node(expr.id, expr.span), || { + + // the construction of a closure itself is not important, + // but we have to consider the closed over variables. + let caps = (*self.ir).captures(expr); + do (*caps).foldr(succ) |cap, succ| { + self.init_from_succ(cap.ln, succ); + let var = self.variable(cap.var_nid, expr.span); + self.acc(cap.ln, var, ACC_READ | ACC_USE); + cap.ln + } + }) } expr_if(cond, then, els) => { @@ -1021,6 +1087,8 @@ impl Liveness { self.propagate_through_loop(expr, Some(cond), blk, succ) } + // Note that labels have been resolved, so we don't need to look + // at the label ident expr_loop(blk, _) => { self.propagate_through_loop(expr, None, blk, succ) } @@ -1062,29 +1130,31 @@ impl Liveness { } expr_break(opt_label) => { - if !self.break_ln.is_valid() { - self.tcx.sess.span_bug( - expr.span, ~"break with invalid break_ln"); - } + // Find which label this break jumps to + let sc = self.find_loop_scope(opt_label, expr.id, expr.span); - if opt_label.is_some() { - self.tcx.sess.span_unimpl(expr.span, ~"labeled break"); - } + // Now that we know the label we're going to, + // look it up in the break loop nodes table - self.break_ln + match self.break_ln.find(sc) { + Some(b) => b, + None => self.tcx.sess.span_bug(expr.span, + ~"Break to unknown label") + } } expr_again(opt_label) => { - if !self.cont_ln.is_valid() { - self.tcx.sess.span_bug( - expr.span, ~"cont with invalid cont_ln"); - } + // Find which label this expr continues to to + let sc = self.find_loop_scope(opt_label, expr.id, expr.span); - if opt_label.is_some() { - self.tcx.sess.span_unimpl(expr.span, ~"labeled again"); - } + // Now that we know the label we're going to, + // look it up in the continue loop nodes table - self.cont_ln + match self.cont_ln.find(sc) { + Some(b) => b, + None => self.tcx.sess.span_bug(expr.span, + ~"Loop to unknown label") + } } expr_move(l, r) | expr_assign(l, r) => { @@ -1314,6 +1384,7 @@ impl Liveness { */ + // first iteration: let mut first_merge = true; let ln = self.live_node(expr.id, expr.span); @@ -1325,8 +1396,11 @@ impl Liveness { self.merge_from_succ(ln, succ, first_merge); first_merge = false; } + debug!("propagate_through_loop: using id for loop body %d %s", + expr.id, block_to_str(body, self.tcx.sess.intr())); + let cond_ln = self.propagate_through_opt_expr(cond, ln); - let body_ln = self.with_loop_nodes(succ, ln, || { + let body_ln = self.with_loop_nodes(expr.id, succ, ln, || { self.propagate_through_block(body, cond_ln) }); @@ -1334,7 +1408,8 @@ impl Liveness { while self.merge_from_succ(ln, body_ln, first_merge) { first_merge = false; assert cond_ln == self.propagate_through_opt_expr(cond, ln); - assert body_ln == self.with_loop_nodes(succ, ln, || { + assert body_ln == self.with_loop_nodes(expr.id, succ, ln, + || { self.propagate_through_block(body, cond_ln) }); } @@ -1342,15 +1417,16 @@ impl Liveness { cond_ln } - fn with_loop_nodes(break_ln: LiveNode, + fn with_loop_nodes(loop_node_id: node_id, + break_ln: LiveNode, cont_ln: LiveNode, f: fn() -> R) -> R { - let bl = self.break_ln, cl = self.cont_ln; - self.break_ln = break_ln; - self.cont_ln = cont_ln; - let r <- f(); - self.break_ln = bl; - self.cont_ln = cl; + debug!("with_loop_nodes: %d %u", loop_node_id, *break_ln); + self.loop_scope.push(loop_node_id); + self.break_ln.insert(loop_node_id, break_ln); + self.cont_ln.insert(loop_node_id, cont_ln); + let r = f(); + self.loop_scope.pop(); move r } } @@ -1526,6 +1602,10 @@ impl @Liveness { } } + /* + Checks whether is live on entry to any of the successors of . + If it is, report an error. + */ fn check_move_from_var(span: span, ln: LiveNode, var: Variable) { debug!("check_move_from_var(%s, %s)", ln.to_str(), var.to_str()); diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 4c9a006007e7..d2cde0420fb6 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1050,7 +1050,7 @@ fn new_block(cx: fn_ctxt, parent: Option, +kind: block_kind, } fn simple_block_scope() -> block_kind { - block_scope({loop_break: None, mut cleanups: ~[], + block_scope({loop_break: None, loop_label: None, mut cleanups: ~[], mut cleanup_paths: ~[], mut landing_pad: None}) } @@ -1067,10 +1067,11 @@ fn scope_block(bcx: block, n, opt_node_info); } -fn loop_scope_block(bcx: block, loop_break: block, n: ~str, - opt_node_info: Option) -> block { +fn loop_scope_block(bcx: block, loop_break: block, loop_label: Option, + n: ~str, opt_node_info: Option) -> block { return new_block(bcx.fcx, Some(bcx), block_scope({ loop_break: Some(loop_break), + loop_label: loop_label, mut cleanups: ~[], mut cleanup_paths: ~[], mut landing_pad: None diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 554a533e110d..7f234349d711 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -445,6 +445,7 @@ enum block_kind { type scope_info = { loop_break: Option, + loop_label: Option, // A list of functions that must be run at when leaving this // block, cleaning up any variables that were introduced in the // block. diff --git a/src/rustc/middle/trans/controlflow.rs b/src/rustc/middle/trans/controlflow.rs index ce32cd0a2dd1..b1ca93f8f8a0 100644 --- a/src/rustc/middle/trans/controlflow.rs +++ b/src/rustc/middle/trans/controlflow.rs @@ -113,7 +113,9 @@ fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) // | body_bcx_out --+ // next_bcx - let loop_bcx = loop_scope_block(bcx, next_bcx, ~"`while`", body.info()); + // tjc: while should have labels... + let loop_bcx = loop_scope_block(bcx, next_bcx, None, ~"`while`", + body.info()); let cond_bcx_in = scope_block(loop_bcx, cond.info(), ~"while loop cond"); let body_bcx_in = scope_block(loop_bcx, body.info(), ~"while loop body"); Br(bcx, loop_bcx.llbb); @@ -133,10 +135,11 @@ fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) return next_bcx; } -fn trans_loop(bcx:block, body: ast::blk) -> block { +fn trans_loop(bcx:block, body: ast::blk, opt_label: Option) -> block { let _icx = bcx.insn_ctxt("trans_loop"); let next_bcx = sub_block(bcx, ~"next"); - let body_bcx_in = loop_scope_block(bcx, next_bcx, ~"`loop`", body.info()); + let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, ~"`loop`", + body.info()); Br(bcx, body_bcx_in.llbb); let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore); cleanup_and_Br(body_bcx_out, body_bcx_in, body_bcx_in.llbb); @@ -201,7 +204,7 @@ fn trans_log(log_ex: @ast::expr, } } -fn trans_break_cont(bcx: block, to_end: bool) +fn trans_break_cont(bcx: block, opt_label: Option, to_end: bool) -> block { let _icx = bcx.insn_ctxt("trans_break_cont"); // Locate closest loop block, outputting cleanup as we go. @@ -209,13 +212,22 @@ fn trans_break_cont(bcx: block, to_end: bool) let mut target; loop { match unwind.kind { - block_scope({loop_break: Some(brk), _}) => { + block_scope({loop_break: Some(brk), loop_label: l, _}) => { + // If we're looking for a labeled loop, check the label... target = if to_end { brk } else { unwind }; - break; + match opt_label { + Some(desired) => match l { + Some(actual) if actual == desired => break, + // If it doesn't match the one we want, + // don't break + _ => () + }, + None => break + } } _ => () } @@ -235,12 +247,12 @@ fn trans_break_cont(bcx: block, to_end: bool) return bcx; } -fn trans_break(bcx: block) -> block { - return trans_break_cont(bcx, true); +fn trans_break(bcx: block, label_opt: Option) -> block { + return trans_break_cont(bcx, label_opt, true); } -fn trans_cont(bcx: block) -> block { - return trans_break_cont(bcx, false); +fn trans_cont(bcx: block, label_opt: Option) -> block { + return trans_break_cont(bcx, label_opt, false); } fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block { diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 30bea1376c00..b0702c80b39b 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -410,16 +410,10 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block { match expr.node { ast::expr_break(label_opt) => { - if label_opt.is_some() { - bcx.tcx().sess.span_unimpl(expr.span, ~"labeled break"); - } - return controlflow::trans_break(bcx); + return controlflow::trans_break(bcx, label_opt); } ast::expr_again(label_opt) => { - if label_opt.is_some() { - bcx.tcx().sess.span_unimpl(expr.span, ~"labeled again"); - } - return controlflow::trans_cont(bcx); + return controlflow::trans_cont(bcx, label_opt); } ast::expr_ret(ex) => { return controlflow::trans_ret(bcx, ex); @@ -436,8 +430,8 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block { ast::expr_while(cond, body) => { return controlflow::trans_while(bcx, cond, body); } - ast::expr_loop(body, _) => { - return controlflow::trans_loop(bcx, body); + ast::expr_loop(body, opt_label) => { + return controlflow::trans_loop(bcx, body, opt_label); } ast::expr_assign(dst, src) => { let src_datum = unpack_datum!(bcx, trans_to_datum(bcx, src)); diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 8d10343d78ee..90aacb4b7ce6 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -46,7 +46,7 @@ use syntax::ast_map::node_id_to_str; use syntax::ast_util::{local_def, respan, split_trait_methods}; use syntax::visit; use metadata::csearch; -use util::common::may_break; +use util::common::{block_query, loop_query}; use syntax::codemap::span; use pat_util::{pat_is_variant, pat_id_map, PatIdMap}; use middle::ty; diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 5f9e584fa7b9..e37c90d98b41 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1665,7 +1665,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, ast::expr_loop(body, _) => { check_block_no_value(fcx, body); fcx.write_ty(id, ty::mk_nil(tcx)); - bot = !may_break(body); + bot = !may_break(tcx, expr.id, body); } ast::expr_match(discrim, arms) => { bot = alt::check_alt(fcx, expr, discrim, arms); @@ -2544,6 +2544,30 @@ fn ast_expr_vstore_to_vstore(fcx: @fn_ctxt, e: @ast::expr, n: uint, } } +// Returns true if b contains a break that can exit from b +fn may_break(cx: ty::ctxt, id: ast::node_id, b: ast::blk) -> bool { + // First: is there an unlabeled break immediately + // inside the loop? + (loop_query(b, |e| { + match e { + ast::expr_break(_) => true, + _ => false + } + })) || + // Second: is there a labeled break with label + // nested anywhere inside the loop? + (block_query(b, |e| { + match e.node { + ast::expr_break(Some(_)) => + match cx.def_map.find(e.id) { + Some(ast::def_label(loop_id)) if id == loop_id => true, + _ => false, + }, + _ => false + } + })) +} + fn check_bounds_are_used(ccx: @crate_ctxt, span: span, tps: ~[ast::ty_param], diff --git a/src/rustc/util/common.rs b/src/rustc/util/common.rs index 123905adba11..0448b022602a 100644 --- a/src/rustc/util/common.rs +++ b/src/rustc/util/common.rs @@ -58,22 +58,19 @@ fn loop_query(b: ast::blk, p: fn@(ast::expr_) -> bool) -> bool { return *rs; } -fn has_nonlocal_exits(b: ast::blk) -> bool { - do loop_query(b) |e| { - match e { - ast::expr_break(_) | ast::expr_again(_) => true, - _ => false - } - } -} - -fn may_break(b: ast::blk) -> bool { - do loop_query(b) |e| { - match e { - ast::expr_break(_) => true, - _ => false - } - } +// Takes a predicate p, returns true iff p is true for any subexpressions +// of b -- skipping any inner loops (loop, while, loop_body) +fn block_query(b: ast::blk, p: fn@(@ast::expr) -> bool) -> bool { + let rs = @mut false; + let visit_expr = + |e: @ast::expr, &&flag: @mut bool, v: visit::vt<@mut bool>| { + *flag |= p(e); + visit::visit_expr(e, flag, v) + }; + let v = visit::mk_vt(@{visit_expr: visit_expr + ,.. *visit::default_visitor()}); + visit::visit_block(b, rs, v); + return *rs; } fn local_rhs_span(l: @ast::local, def: span) -> span { diff --git a/src/test/run-pass/issue-2216.rs b/src/test/run-pass/issue-2216.rs new file mode 100644 index 000000000000..11815db17632 --- /dev/null +++ b/src/test/run-pass/issue-2216.rs @@ -0,0 +1,22 @@ +fn main() { + let mut x = 0; + + loop foo: { + loop bar: { + loop quux: { + if 1 == 2 { + break foo; + } + else { + break bar; + } + } + loop foo; + } + x = 42; + break; + } + + error!("%?", x); + assert(x == 42); +} \ No newline at end of file From dca0776747d62767b806aa32926301be949ffde7 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Oct 2012 09:44:56 -0700 Subject: [PATCH 284/292] Incorporate review comments (mostly fixing indentation) Previous commit was r=nmatsakis --- src/rustc/middle/liveness.rs | 20 ++++++++++---------- src/rustc/middle/trans/controlflow.rs | 11 +++++------ src/rustc/middle/typeck/check.rs | 23 +++++++++++------------ 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 184d694a50c5..2ed72a68f1bd 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -502,9 +502,9 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) { } expr_fn(_, _, _, cap_clause) | expr_fn_block(_, _, cap_clause) => { - // Interesting control flow (for loops can contain labeled - // breaks or continues) - self.add_live_node_for_node(expr.id, ExprNode(expr.span)); + // Interesting control flow (for loops can contain labeled + // breaks or continues) + self.add_live_node_for_node(expr.id, ExprNode(expr.span)); // Make a live_node for each captured variable, with the span // being the location that the variable is used. This results @@ -596,7 +596,7 @@ struct Liveness { users: ~[mut users], // The list of node IDs for the nested loop scopes // we're in. - mut loop_scope: @DVec, + loop_scope: DVec, // mappings from loop node ID to LiveNode // ("break" label should map to loop node ID, // it probably doesn't now) @@ -778,10 +778,10 @@ impl Liveness { Some(_) => // Refers to a labeled loop. Use the results of resolve // to find with one match self.tcx.def_map.find(id) { - Some(def_label(loop_id)) => loop_id, - _ => self.tcx.sess.span_bug(sp, ~"Label on break/loop \ - doesn't refer to a loop") - }, + Some(def_label(loop_id)) => loop_id, + _ => self.tcx.sess.span_bug(sp, ~"Label on break/loop \ + doesn't refer to a loop") + }, None => // Vanilla 'break' or 'loop', so use the enclosing // loop scope @@ -1024,7 +1024,7 @@ impl Liveness { } fn propagate_through_expr(expr: @expr, succ: LiveNode) -> LiveNode { - debug!("propagate_through_expr: %s", + debug!("propagate_through_expr: %s", expr_to_str(expr, self.tcx.sess.intr())); match expr.node { @@ -1039,7 +1039,7 @@ impl Liveness { } expr_fn(_, _, blk, _) | expr_fn_block(_, blk, _) => { - debug!("%s is an expr_fn or expr_fn_block", + debug!("%s is an expr_fn or expr_fn_block", expr_to_str(expr, self.tcx.sess.intr())); /* diff --git a/src/rustc/middle/trans/controlflow.rs b/src/rustc/middle/trans/controlflow.rs index b1ca93f8f8a0..59a733433bf2 100644 --- a/src/rustc/middle/trans/controlflow.rs +++ b/src/rustc/middle/trans/controlflow.rs @@ -113,7 +113,6 @@ fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) // | body_bcx_out --+ // next_bcx - // tjc: while should have labels... let loop_bcx = loop_scope_block(bcx, next_bcx, None, ~"`while`", body.info()); let cond_bcx_in = scope_block(loop_bcx, cond.info(), ~"while loop cond"); @@ -214,11 +213,11 @@ fn trans_break_cont(bcx: block, opt_label: Option, to_end: bool) match unwind.kind { block_scope({loop_break: Some(brk), loop_label: l, _}) => { // If we're looking for a labeled loop, check the label... - target = if to_end { - brk - } else { - unwind - }; + target = if to_end { + brk + } else { + unwind + }; match opt_label { Some(desired) => match l { Some(actual) if actual == desired => break, diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index e37c90d98b41..cc542e9f3663 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2550,22 +2550,21 @@ fn may_break(cx: ty::ctxt, id: ast::node_id, b: ast::blk) -> bool { // inside the loop? (loop_query(b, |e| { match e { - ast::expr_break(_) => true, - _ => false + ast::expr_break(_) => true, + _ => false } })) || // Second: is there a labeled break with label // nested anywhere inside the loop? - (block_query(b, |e| { - match e.node { - ast::expr_break(Some(_)) => - match cx.def_map.find(e.id) { - Some(ast::def_label(loop_id)) if id == loop_id => true, - _ => false, - }, - _ => false - } - })) + (block_query(b, |e| { + match e.node { + ast::expr_break(Some(_)) => + match cx.def_map.find(e.id) { + Some(ast::def_label(loop_id)) if id == loop_id => true, + _ => false, + }, + _ => false + }})) } fn check_bounds_are_used(ccx: @crate_ctxt, From 14e7df7d1a7da2b21932d546aa63f26e953cbb5b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Oct 2012 10:54:23 -0700 Subject: [PATCH 285/292] Fix breakage (forgot to commit this... --- src/rustc/middle/liveness.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 2ed72a68f1bd..da3e7b175d07 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -617,7 +617,7 @@ fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness { vec::to_mut( vec::from_elem(ir.num_live_nodes * ir.num_vars, invalid_users())), - loop_scope: @DVec(), + loop_scope: DVec(), break_ln: HashMap(), cont_ln: HashMap() } From 64e1ecb939542d689358ef05963db214e4ea198d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 22 Oct 2012 12:02:55 -0700 Subject: [PATCH 286/292] Long lines --- src/rustc/middle/trans/base.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 2d3e13b14a21..bf66ccbfeb5f 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -267,7 +267,8 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, fn non_gc_box_cast(bcx: block, val: ValueRef) -> ValueRef { debug!("non_gc_box_cast"); add_comment(bcx, ~"non_gc_box_cast"); - assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace || bcx.unreachable); + assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace + || bcx.unreachable); let non_gc_t = T_ptr(llvm::LLVMGetElementType(val_ty(val))); PointerCast(bcx, val, non_gc_t) } From 7947bb1732f513906acef459a6e8c839481f135b Mon Sep 17 00:00:00 2001 From: Gareth Daniel Smith Date: Mon, 22 Oct 2012 20:56:00 +0100 Subject: [PATCH 287/292] Fix and test for issue #3780. --- src/rustdoc/attr_parser.rs | 42 +++++++++++++++----------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/src/rustdoc/attr_parser.rs b/src/rustdoc/attr_parser.rs index d2b314adf9c9..2b16112fe16c 100644 --- a/src/rustdoc/attr_parser.rs +++ b/src/rustdoc/attr_parser.rs @@ -36,27 +36,6 @@ mod test { } } -fn doc_meta( - attrs: ~[ast::attribute] -) -> Option<@ast::meta_item> { - - /*! - * Given a vec of attributes, extract the meta_items contained in the \ - * doc attribute - */ - - let doc_metas = doc_metas(attrs); - if vec::is_not_empty(doc_metas) { - if vec::len(doc_metas) != 1u { - warn!("ignoring %u doc attributes", vec::len(doc_metas) - 1u); - } - Some(doc_metas[0]) - } else { - None - } - -} - fn doc_metas( attrs: ~[ast::attribute] ) -> ~[@ast::meta_item] { @@ -102,11 +81,13 @@ fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() { } fn parse_desc(attrs: ~[ast::attribute]) -> Option<~str> { - match doc_meta(attrs) { - Some(meta) => { - attr::get_meta_item_value_str(meta) - } - None => None + let doc_strs = do doc_metas(attrs).filter_map |meta| { + attr::get_meta_item_value_str(*meta) + }; + if doc_strs.is_empty() { + None + } else { + Some(str::connect(doc_strs, "\n")) } } @@ -158,3 +139,12 @@ fn should_not_parse_non_hidden_attribute() { let attrs = test::parse_attributes(source); assert parse_hidden(attrs) == false; } + +#[test] +fn should_concatenate_multiple_doc_comments() { + let source = ~"/// foo\n/// bar"; + let desc = parse_desc(test::parse_attributes(source)); + assert desc == Some(~"foo\nbar"); +} + + From 5fc4e51ab77ad0fce9c16c7bbc06c5f68008c52b Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 22 Oct 2012 13:12:16 -0700 Subject: [PATCH 288/292] docs: Remove unfinished sentence in manual. Closes #3806 --- doc/rust.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 568f42976358..7e1c6e6e088b 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2475,7 +2475,6 @@ assert (i == 3); ~~~~ All accessible elements of a vector are always initialized, and access to a vector is always bounds-checked. -In the case of a definite- ### Structure types From 5a86f5d084b7580ec6c94c2be213d660d0ce0f67 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 22 Oct 2012 13:33:12 -0700 Subject: [PATCH 289/292] rustc: Convert two printlns in trans into debug! --- src/rustc/middle/trans/meth.rs | 2 +- src/rustc/middle/trans/monomorphize.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs index fadde08b9f89..20dba35b231b 100644 --- a/src/rustc/middle/trans/meth.rs +++ b/src/rustc/middle/trans/meth.rs @@ -155,7 +155,7 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id, // Get the ID of the impl we're inside. let impl_def_id = bcx.fcx.impl_id.get(); - io::println(fmt!("impl_def_id is %?", impl_def_id)); + debug!("impl_def_id is %?", impl_def_id); // Get the ID of the method we're calling. let method_name = diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index aadd6fc7957a..c2f106f631b1 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -203,7 +203,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, ast_map::node_trait_method(@ast::provided(mth), _, pt) => { let d = mk_lldecl(); set_inline_hint_if_appr(mth.attrs, d); - io::println(fmt!("monomorphic_fn impl_did_opt is %?", impl_did_opt)); + debug!("monomorphic_fn impl_did_opt is %?", impl_did_opt); meth::trans_method(ccx, *pt, mth, psubsts, None, d, impl_did_opt.get()); d From 763a8e7b47f0354f96fb9e13c46d76c4c62c8a97 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 22 Oct 2012 14:04:22 -0700 Subject: [PATCH 290/292] xfail-fast issue-3656 --- src/test/run-pass/issue-3656.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs index 330ec59a0a8f..5e9835b4f6f2 100644 --- a/src/test/run-pass/issue-3656.rs +++ b/src/test/run-pass/issue-3656.rs @@ -1,3 +1,4 @@ +// xfail-fast Can't redeclare malloc with wrong signature because bugs // Issue #3656 // Incorrect struct size computation in the FFI, because of not taking // the alignment of elements into account. From f1da4424bf7c5a81b7eb37093d3d7e80b76b0067 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Mon, 22 Oct 2012 22:21:29 +0200 Subject: [PATCH 291/292] `submodule sync` won't work in a leaf submodule. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 9da652762a74..a8c3ba59e61a 100755 --- a/configure +++ b/configure @@ -595,7 +595,7 @@ then need_ok "git failed" msg "git: submodule foreach sync" - "${CFG_GIT}" submodule --quiet foreach --recursive git submodule sync + "${CFG_GIT}" submodule --quiet foreach --recursive 'if test -e .gitmodules; then git submodule sync; fi' need_ok "git failed" msg "git: submodule foreach update" From 9ee5fff4f16cfc3390bd69abbb46b0a68521667c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 22 Oct 2012 14:36:29 -0700 Subject: [PATCH 292/292] Add Gabriel to AUTHORS.txt --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 90690a0a3eaf..9ab084c5db2d 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -41,6 +41,7 @@ Erick Tryzelaar Erik Rose Evan McClanahan Francisco Souza +Gabriel Gareth Daniel Smith Glenn Willen Gonçalo Cabrita <_@gmcabrita.com>